From d07b947962ca7b7e576a4bd9bab412b73e77c84b Mon Sep 17 00:00:00 2001 From: Jury Verrigni Date: Wed, 18 Jan 2017 13:05:22 +0000 Subject: [PATCH 1/8] Implemented guest access --- client/startup/requestGuestAccount.js | 15 +++++++++++ packages/rocketchat-i18n/i18n/en.i18n.json | 3 +++ .../server/functions/sendMessage.coffee | 2 +- .../server/methods/sendMessage.coffee | 3 +++ .../server/models/Messages.coffee | 2 ++ .../server/startup/settings.coffee | 1 + .../rocketchat-theme/client/imports/base.less | 1 + .../client/login/form.coffee | 10 +++++++ .../client/login/form.html | 5 ++++ .../message/messageBox.coffee | 4 +++ .../message/messageBox.html | 2 +- .../client/accountBox.coffee | 10 +++++++ .../client/accountBox.html | 18 ++++++++----- packages/rocketchat-ui/lib/fileUpload.coffee | 2 ++ server/lib/accounts.js | 7 ++++- server/methods/getGuestAccount.coffee | 26 +++++++++++++++++++ server/methods/removeGuestUser.js | 11 ++++++++ server/publications/userData.js | 1 + 18 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 client/startup/requestGuestAccount.js create mode 100644 server/methods/getGuestAccount.coffee create mode 100644 server/methods/removeGuestUser.js diff --git a/client/startup/requestGuestAccount.js b/client/startup/requestGuestAccount.js new file mode 100644 index 000000000000..597d3c993ca7 --- /dev/null +++ b/client/startup/requestGuestAccount.js @@ -0,0 +1,15 @@ +Meteor.startup(function() { + Tracker.autorun(function() { + if (!Session.get('no-guest')) { + if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowGuestAccess') === true) { + Meteor.call('getGuestAccount', function(error, user) { + if (error) { + console.log (error); + return; + } + Meteor.loginWithPassword(user, ''); + }); + } + } + }); +}); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 571c573e2d12..8ea5aa910c71 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -21,6 +21,7 @@ "Accounts_AllowedDomainsList": "Allowed Domains List", "Accounts_AllowedDomainsList_Description": "Comma-separated list of allowed domains", "Accounts_AllowEmailChange": "Allow Email Change", + "Accounts_AllowGuestAccess_Description": "Allow anonymous/guest access", "Accounts_AllowPasswordChange": "Allow Password Change", "Accounts_AllowUserAvatarChange": "Allow User Avatar Change", "Accounts_AllowUsernameChange": "Allow Username Change", @@ -897,6 +898,8 @@ "Log_View_Limit": "Log View Limit", "Logged_out_of_other_clients_successfully": "Logged out of other clients successfully", "Login": "Login", + "Login_As_Guest": "Login as Guest", + "Login_Or_Register_Message_Box": "Login or Register to send messages", "Login_with": "Login with %s", "Logout": "Logout", "Logout_Others": "Logout From Other Logged In Locations", diff --git a/packages/rocketchat-lib/server/functions/sendMessage.coffee b/packages/rocketchat-lib/server/functions/sendMessage.coffee index bdce87faba4d..572123b5cb1f 100644 --- a/packages/rocketchat-lib/server/functions/sendMessage.coffee +++ b/packages/rocketchat-lib/server/functions/sendMessage.coffee @@ -1,5 +1,5 @@ RocketChat.sendMessage = (user, message, room, upsert = false) -> - if not user or not message or not room._id + if not user or not message or not room._id or user.guestId return false unless message.ts? diff --git a/packages/rocketchat-lib/server/methods/sendMessage.coffee b/packages/rocketchat-lib/server/methods/sendMessage.coffee index 95e8f71a66ab..2354a9c12fe9 100644 --- a/packages/rocketchat-lib/server/methods/sendMessage.coffee +++ b/packages/rocketchat-lib/server/methods/sendMessage.coffee @@ -8,6 +8,9 @@ Meteor.methods if not Meteor.userId() throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'sendMessage' }) + if Meteor.user().guestId + throw new Meteor.Error('error-invalid-user', "Guests cannot send messages", { method: 'sendMessage' }) + if message.ts tsDiff = Math.abs(moment(message.ts).diff()) if tsDiff > 60000 diff --git a/packages/rocketchat-lib/server/models/Messages.coffee b/packages/rocketchat-lib/server/models/Messages.coffee index 8ac7b4efcd7b..b3dbf2981d93 100644 --- a/packages/rocketchat-lib/server/models/Messages.coffee +++ b/packages/rocketchat-lib/server/models/Messages.coffee @@ -369,6 +369,8 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base # INSERT createWithTypeRoomIdMessageAndUser: (type, roomId, message, user, extraData) -> + if user.guestId + return room = RocketChat.models.Rooms.findOneById roomId, { fields: { sysMes: 1 }} if room?.sysMes is false return diff --git a/packages/rocketchat-lib/server/startup/settings.coffee b/packages/rocketchat-lib/server/startup/settings.coffee index 9690a669d0d0..0129aa4616da 100644 --- a/packages/rocketchat-lib/server/startup/settings.coffee +++ b/packages/rocketchat-lib/server/startup/settings.coffee @@ -4,6 +4,7 @@ RocketChat.settings.add('uniqueID', process.env.DEPLOYMENT_ID or Random.id(), { # When you define a setting and want to add a description, you don't need to automatically define the i18nDescription # if you add a node to the i18n.json with the same setting name but with `_Description` it will automatically work. RocketChat.settings.addGroup 'Accounts', -> + @add 'Accounts_AllowGuestAccess', false, { type: 'boolean', public: true} @add 'Accounts_AllowDeleteOwnAccount', false, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowUserProfileChange', value: true } } @add 'Accounts_AllowUserProfileChange', true, { type: 'boolean', public: true } @add 'Accounts_AllowUserAvatarChange', true, { type: 'boolean', public: true } diff --git a/packages/rocketchat-theme/client/imports/base.less b/packages/rocketchat-theme/client/imports/base.less index 78381af1c3cf..09008e42cea3 100644 --- a/packages/rocketchat-theme/client/imports/base.less +++ b/packages/rocketchat-theme/client/imports/base.less @@ -4001,6 +4001,7 @@ body:not(.is-cordova) { .submit, .register, .forgot-password, + .login-as-guest, .back-to-login { margin-top: 12px; } diff --git a/packages/rocketchat-ui-login/client/login/form.coffee b/packages/rocketchat-ui-login/client/login/form.coffee index f995b470623d..f438d0962915 100644 --- a/packages/rocketchat-ui-login/client/login/form.coffee +++ b/packages/rocketchat-ui-login/client/login/form.coffee @@ -29,6 +29,9 @@ Template.loginForm.helpers registrationAllowed: -> return RocketChat.settings.get('Accounts_RegistrationForm') is 'Public' or Template.instance().validSecretURL?.get() + guestLoginAllowed: -> + return RocketChat.settings.get('Accounts_AllowGuestAccess') + linkReplacementText: -> return RocketChat.settings.get('Accounts_RegistrationForm_LinkReplacementText') @@ -128,6 +131,13 @@ Template.loginForm.events Template.instance().state.set 'forgot-password' RocketChat.callbacks.run('loginPageStateChange', Template.instance().state.get()); + 'click .login-as-guest': -> + Meteor.call 'getGuestAccount', (error, user) -> + if error + console.log (error); + return + Meteor.loginWithPassword(user, ''); + 'click .one-passsword': -> if not OnePassword?.findLoginForUrl? return diff --git a/packages/rocketchat-ui-login/client/login/form.html b/packages/rocketchat-ui-login/client/login/form.html index c761e8f19c5b..f7d5f33171a9 100644 --- a/packages/rocketchat-ui-login/client/login/form.html +++ b/packages/rocketchat-ui-login/client/login/form.html @@ -104,6 +104,11 @@

{{{_ "Registration_Succeeded"}}}

{{/if}} + {{#if guestLoginAllowed}} +
+ +
+ {{/if}} {{/if}} {{/if}} {{/if}} diff --git a/packages/rocketchat-ui-message/message/messageBox.coffee b/packages/rocketchat-ui-message/message/messageBox.coffee index 0948937f8e13..f08c81c6f5f8 100644 --- a/packages/rocketchat-ui-message/message/messageBox.coffee +++ b/packages/rocketchat-ui-message/message/messageBox.coffee @@ -9,6 +9,10 @@ katexSyntax = -> return false Template.messageBox.helpers + guestDisabled: -> + return if Meteor.user().guestId then 'disabled' else '' + placeholder: -> + return if Meteor.user().guestId then t('Login_Or_Register_Message_Box') else t('Message') roomName: -> roomData = Session.get('roomData' + this._id) return '' unless roomData diff --git a/packages/rocketchat-ui-message/message/messageBox.html b/packages/rocketchat-ui-message/message/messageBox.html index 65a36bf0e109..28587c6a716b 100644 --- a/packages/rocketchat-ui-message/message/messageBox.html +++ b/packages/rocketchat-ui-message/message/messageBox.html @@ -5,7 +5,7 @@ {{#if allowedToSend}}
- +
diff --git a/packages/rocketchat-ui-sidenav/client/accountBox.coffee b/packages/rocketchat-ui-sidenav/client/accountBox.coffee index b0f2bf2741b2..f262f2abd089 100644 --- a/packages/rocketchat-ui-sidenav/client/accountBox.coffee +++ b/packages/rocketchat-ui-sidenav/client/accountBox.coffee @@ -17,6 +17,9 @@ Template.accountBox.helpers username: username } + isGuest: -> + return Meteor.user()?.guestId + showAdminOption: -> return RocketChat.authz.hasAtLeastOnePermission( ['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]) or RocketChat.AdminBox.getOptions().length > 0 @@ -36,6 +39,7 @@ Template.accountBox.events event.preventDefault() user = Meteor.user() Meteor.logout -> + Session.set 'no-guest', true RocketChat.callbacks.run 'afterLogoutCleanUp', user Meteor.call('logoutCleanUp', user) FlowRouter.go 'home' @@ -58,6 +62,12 @@ Template.accountBox.events event.preventDefault(); AccountBox.openFlex() + 'click #login': -> + user = Meteor.user() + Accounts.logout -> + Session.set 'no-guest', true + Meteor.call 'removeGuestUser', user + 'click .account-box-item': -> if @href FlowRouter.go @href diff --git a/packages/rocketchat-ui-sidenav/client/accountBox.html b/packages/rocketchat-ui-sidenav/client/accountBox.html index 61282239834d..408bf2b0c360 100644 --- a/packages/rocketchat-ui-sidenav/client/accountBox.html +++ b/packages/rocketchat-ui-sidenav/client/accountBox.html @@ -13,18 +13,24 @@

{{username}}

{{/with}} diff --git a/packages/rocketchat-ui/lib/fileUpload.coffee b/packages/rocketchat-ui/lib/fileUpload.coffee index 690e4c707111..6da95d149456 100644 --- a/packages/rocketchat-ui/lib/fileUpload.coffee +++ b/packages/rocketchat-ui/lib/fileUpload.coffee @@ -14,6 +14,8 @@ readAsArrayBuffer = (file, callback) -> @fileUpload = (files) -> + if Meteor.user().guestId + return roomId = Session.get('openedRoom') files = [].concat files diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 5dad2be2517c..cbbe9bf2ef90 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -112,9 +112,12 @@ Accounts.insertUserDoc = _.wrap(Accounts.insertUserDoc, function(insertUserDoc, _id: _id }); + const isGuest = user.username && user.username.match(/guest-\d/); + if (user.username && options.joinDefaultChannels !== false && user.joinDefaultChannels !== false) { Meteor.runAsUser(_id, function() { - return Meteor.call('joinDefaultChannels', options.joinDefaultChannelsSilenced); + const silencedJoin = (isGuest ? true : options.joinDefaultChannelsSilenced) + return Meteor.call('joinDefaultChannels', silencedJoin); }); } @@ -130,6 +133,8 @@ Accounts.insertUserDoc = _.wrap(Accounts.insertUserDoc, function(insertUserDoc, if (hasAdmin) { roles.push('user'); + } else if (isGuest) { + roles.push('guest'); } else { roles.push('admin'); } diff --git a/server/methods/getGuestAccount.coffee b/server/methods/getGuestAccount.coffee new file mode 100644 index 000000000000..83923272a779 --- /dev/null +++ b/server/methods/getGuestAccount.coffee @@ -0,0 +1,26 @@ +Meteor.methods + getGuestAccount: -> + lastGuest = RocketChat.models.Users.findOne({'guestId': {$gt: 0}}, {sort: {DateTime: -1, limit: 1}}); + guestId = 1 + if lastGuest + guestId = lastGuest.guestId + 1 + + username = 'guest-' + guestId + + userId = Accounts.createUser + username: username + email: username + '@tobedeleted.guest' + password: '' + profile: + name: username + + Accounts.setPassword userId, '' + + RocketChat.models.Users.update userId, + $set: + guestId: guestId + + RocketChat.models.Roles.removeUserRoles userId, 'create-d' + RocketChat.models.Roles.removeUserRoles userId, 'create-p' + + username diff --git a/server/methods/removeGuestUser.js b/server/methods/removeGuestUser.js new file mode 100644 index 000000000000..96ca5766b95d --- /dev/null +++ b/server/methods/removeGuestUser.js @@ -0,0 +1,11 @@ +Meteor.methods({ + removeGuestUser(user) { + if (user.guestId) { + // Just in case of data manipulation + let userCheck = RocketChat.models.Users.find({_id: user._id, guestId: user.guestId}); + if (userCheck) { + RocketChat.models.Users.remove(user._id); + } + } + } +}); diff --git a/server/publications/userData.js b/server/publications/userData.js index 2d12096f0210..c57401048861 100644 --- a/server/publications/userData.js +++ b/server/publications/userData.js @@ -15,6 +15,7 @@ Meteor.publish('userData', function() { language: 1, settings: 1, roles: 1, + guestId: 1, active: 1, defaultRoom: 1, customFields: 1, From ba5e1b525f66919ff4ae1837c4c4125e2710afce Mon Sep 17 00:00:00 2001 From: Jury Verrigni Date: Sat, 21 Jan 2017 18:18:32 +0000 Subject: [PATCH 2/8] Added guest cleanup on session expired/destroyed --- client/startup/requestGuestAccount.js | 4 +++- packages/rocketchat-i18n/i18n/en.i18n.json | 3 ++- .../rocketchat-lib/server/startup/settings.coffee | 1 + .../rocketchat-ui-sidenav/client/accountBox.coffee | 4 +++- server/methods/removeGuestUser.js | 11 ----------- server/startup/removeOfflineGuests.coffee | 12 ++++++++++++ 6 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 server/methods/removeGuestUser.js create mode 100644 server/startup/removeOfflineGuests.coffee diff --git a/client/startup/requestGuestAccount.js b/client/startup/requestGuestAccount.js index 597d3c993ca7..8351b0e529a4 100644 --- a/client/startup/requestGuestAccount.js +++ b/client/startup/requestGuestAccount.js @@ -1,7 +1,9 @@ Meteor.startup(function() { Tracker.autorun(function() { if (!Session.get('no-guest')) { - if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowGuestAccess') === true) { + if (!Meteor.userId() + && RocketChat.settings.get('Accounts_AllowGuestAccess') === true + && RocketChat.settings.get('Accounts_AutomaticallyLoginAsGuest')) { Meteor.call('getGuestAccount', function(error, user) { if (error) { console.log (error); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8ea5aa910c71..f4c3f5bfd1a4 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -21,11 +21,12 @@ "Accounts_AllowedDomainsList": "Allowed Domains List", "Accounts_AllowedDomainsList_Description": "Comma-separated list of allowed domains", "Accounts_AllowEmailChange": "Allow Email Change", - "Accounts_AllowGuestAccess_Description": "Allow anonymous/guest access", + "Accounts_AllowGuestAccess": "Allow anonymous/guest access", "Accounts_AllowPasswordChange": "Allow Password Change", "Accounts_AllowUserAvatarChange": "Allow User Avatar Change", "Accounts_AllowUsernameChange": "Allow Username Change", "Accounts_AllowUserProfileChange": "Allow User Profile Change", + "Accounts_AutomaticallyLoginAsGuest": "Automatically login as guest", "Accounts_AvatarResize": "Resize Avatars", "Accounts_AvatarSize": "Avatar Size", "Accounts_AvatarStorePath": "Avatar Storage Path", diff --git a/packages/rocketchat-lib/server/startup/settings.coffee b/packages/rocketchat-lib/server/startup/settings.coffee index 0129aa4616da..87138e2e4769 100644 --- a/packages/rocketchat-lib/server/startup/settings.coffee +++ b/packages/rocketchat-lib/server/startup/settings.coffee @@ -5,6 +5,7 @@ RocketChat.settings.add('uniqueID', process.env.DEPLOYMENT_ID or Random.id(), { # if you add a node to the i18n.json with the same setting name but with `_Description` it will automatically work. RocketChat.settings.addGroup 'Accounts', -> @add 'Accounts_AllowGuestAccess', false, { type: 'boolean', public: true} + @add 'Accounts_AutomaticallyLoginAsGuest', true, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowGuestAccess', value: true }} @add 'Accounts_AllowDeleteOwnAccount', false, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowUserProfileChange', value: true } } @add 'Accounts_AllowUserProfileChange', true, { type: 'boolean', public: true } @add 'Accounts_AllowUserAvatarChange', true, { type: 'boolean', public: true } diff --git a/packages/rocketchat-ui-sidenav/client/accountBox.coffee b/packages/rocketchat-ui-sidenav/client/accountBox.coffee index f262f2abd089..383e97bf8b7f 100644 --- a/packages/rocketchat-ui-sidenav/client/accountBox.coffee +++ b/packages/rocketchat-ui-sidenav/client/accountBox.coffee @@ -66,7 +66,9 @@ Template.accountBox.events user = Meteor.user() Accounts.logout -> Session.set 'no-guest', true - Meteor.call 'removeGuestUser', user + RocketChat.callbacks.run 'afterLogoutCleanUp', user + Meteor.call 'logoutCleanUp', user + FlowRouter.go 'home' 'click .account-box-item': -> if @href diff --git a/server/methods/removeGuestUser.js b/server/methods/removeGuestUser.js deleted file mode 100644 index 96ca5766b95d..000000000000 --- a/server/methods/removeGuestUser.js +++ /dev/null @@ -1,11 +0,0 @@ -Meteor.methods({ - removeGuestUser(user) { - if (user.guestId) { - // Just in case of data manipulation - let userCheck = RocketChat.models.Users.find({_id: user._id, guestId: user.guestId}); - if (userCheck) { - RocketChat.models.Users.remove(user._id); - } - } - } -}); diff --git a/server/startup/removeOfflineGuests.coffee b/server/startup/removeOfflineGuests.coffee new file mode 100644 index 000000000000..45286a4020d7 --- /dev/null +++ b/server/startup/removeOfflineGuests.coffee @@ -0,0 +1,12 @@ +Meteor.startup -> + query = + username: + $exists: 1 + status: + $in: ['online', 'away', 'busy'] + RocketChat.models.Users.find(query).observeChanges + removed: (id) -> + user = RocketChat.models.Users.findOne + _id: id + if user.guestId + RocketChat.models.Users.remove id From 05bb71f1ca289f880d87483e0a00384cbaafbfce Mon Sep 17 00:00:00 2001 From: Jury Verrigni Date: Thu, 26 Jan 2017 19:49:12 +0000 Subject: [PATCH 3/8] Renamed guests' username to anonymous-#. Disabled attachments in message box --- .../message/messageBox.coffee | 8 +++--- server/methods/getGuestAccount.coffee | 26 ------------------ server/methods/getGuestAccount.js | 27 +++++++++++++++++++ server/startup/removeOfflineGuests.coffee | 12 --------- server/startup/removeOfflineGuests.js | 14 ++++++++++ 5 files changed, 46 insertions(+), 41 deletions(-) delete mode 100644 server/methods/getGuestAccount.coffee create mode 100644 server/methods/getGuestAccount.js delete mode 100644 server/startup/removeOfflineGuests.coffee create mode 100644 server/startup/removeOfflineGuests.js diff --git a/packages/rocketchat-ui-message/message/messageBox.coffee b/packages/rocketchat-ui-message/message/messageBox.coffee index f08c81c6f5f8..24da97ef4134 100644 --- a/packages/rocketchat-ui-message/message/messageBox.coffee +++ b/packages/rocketchat-ui-message/message/messageBox.coffee @@ -91,6 +91,8 @@ Template.messageBox.helpers return RocketChat.settings.get('FileUpload_MediaTypeWhiteList') showFileUpload: -> + if Meteor.user().guestId + return false if (RocketChat.settings.get('FileUpload_Enabled')) roomData = Session.get('roomData' + this._id) if roomData?.t is 'd' @@ -102,13 +104,13 @@ Template.messageBox.helpers showMic: -> - return Template.instance().showMicButton.get() + return Template.instance().showMicButton.get() and not Meteor.user().guestId showVRec: -> - return Template.instance().showVideoRec.get() + return Template.instance().showVideoRec.get() and not Meteor.user().guestId showSend: -> - if not Template.instance().isMessageFieldEmpty.get() + if not Template.instance().isMessageFieldEmpty.get() and not Meteor.user().guestId return 'show-send' showLocation: -> diff --git a/server/methods/getGuestAccount.coffee b/server/methods/getGuestAccount.coffee deleted file mode 100644 index 83923272a779..000000000000 --- a/server/methods/getGuestAccount.coffee +++ /dev/null @@ -1,26 +0,0 @@ -Meteor.methods - getGuestAccount: -> - lastGuest = RocketChat.models.Users.findOne({'guestId': {$gt: 0}}, {sort: {DateTime: -1, limit: 1}}); - guestId = 1 - if lastGuest - guestId = lastGuest.guestId + 1 - - username = 'guest-' + guestId - - userId = Accounts.createUser - username: username - email: username + '@tobedeleted.guest' - password: '' - profile: - name: username - - Accounts.setPassword userId, '' - - RocketChat.models.Users.update userId, - $set: - guestId: guestId - - RocketChat.models.Roles.removeUserRoles userId, 'create-d' - RocketChat.models.Roles.removeUserRoles userId, 'create-p' - - username diff --git a/server/methods/getGuestAccount.js b/server/methods/getGuestAccount.js new file mode 100644 index 000000000000..779209f4a21c --- /dev/null +++ b/server/methods/getGuestAccount.js @@ -0,0 +1,27 @@ +Meteor.methods({ + getGuestAccount: () => { + let guestId = 1; + let lastGuest = RocketChat.models.Users.findOne({guestId: {$gt: 0}}, {sort: {DateTime: -1, limit: 1}}); + if (lastGuest) { + guestId = lastGuest.guestId + 1; + } + let username = 'anonymous-' + guestId; + while (RocketChat.models.Users.findOne({ username: username })) { + guestId++; + username = 'anonymous-' + guestId; + } + + let userId = Accounts.createUser({ + username: username, + email: username + '@rocket-chat.guest', + password: '', + profile: {name: username} + }); + + Accounts.setPassword(userId, ''); + + RocketChat.models.Users.update(userId, {$set: {guestId: guestId}}); + + return username; + } +}); diff --git a/server/startup/removeOfflineGuests.coffee b/server/startup/removeOfflineGuests.coffee deleted file mode 100644 index 45286a4020d7..000000000000 --- a/server/startup/removeOfflineGuests.coffee +++ /dev/null @@ -1,12 +0,0 @@ -Meteor.startup -> - query = - username: - $exists: 1 - status: - $in: ['online', 'away', 'busy'] - RocketChat.models.Users.find(query).observeChanges - removed: (id) -> - user = RocketChat.models.Users.findOne - _id: id - if user.guestId - RocketChat.models.Users.remove id diff --git a/server/startup/removeOfflineGuests.js b/server/startup/removeOfflineGuests.js new file mode 100644 index 000000000000..3d598396576d --- /dev/null +++ b/server/startup/removeOfflineGuests.js @@ -0,0 +1,14 @@ +Meteor.startup(() => { + let query = { + username: {$exists: 1}, + status: {$in: ['online', 'away', 'busy']} + }; + RocketChat.models.Users.find(query).observeChanges({ + removed: id => { + let user = RocketChat.models.Users.findOne({_id: id}); + if (user && user.guestId) { + RocketChat.models.Users.remove(id); + } + } + }); +}); From 7933cb0f6e78ea0a17a3dbec43a654bc3b086ce4 Mon Sep 17 00:00:00 2001 From: Jury Verrigni Date: Thu, 26 Jan 2017 20:49:32 +0000 Subject: [PATCH 4/8] Changed anonymous creation logic --- client/startup/requestGuestAccount.js | 2 +- server/lib/accounts.js | 2 +- server/methods/getGuestAccount.js | 27 +++++++++++++++++++-------- server/startup/removeOfflineGuests.js | 4 ++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/client/startup/requestGuestAccount.js b/client/startup/requestGuestAccount.js index 8351b0e529a4..c018836c6ce1 100644 --- a/client/startup/requestGuestAccount.js +++ b/client/startup/requestGuestAccount.js @@ -2,7 +2,7 @@ Meteor.startup(function() { Tracker.autorun(function() { if (!Session.get('no-guest')) { if (!Meteor.userId() - && RocketChat.settings.get('Accounts_AllowGuestAccess') === true + && RocketChat.settings.get('Accounts_AllowGuestAccess') && RocketChat.settings.get('Accounts_AutomaticallyLoginAsGuest')) { Meteor.call('getGuestAccount', function(error, user) { if (error) { diff --git a/server/lib/accounts.js b/server/lib/accounts.js index cbbe9bf2ef90..aa0c056a8d3e 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -116,7 +116,7 @@ Accounts.insertUserDoc = _.wrap(Accounts.insertUserDoc, function(insertUserDoc, if (user.username && options.joinDefaultChannels !== false && user.joinDefaultChannels !== false) { Meteor.runAsUser(_id, function() { - const silencedJoin = (isGuest ? true : options.joinDefaultChannelsSilenced) + const silencedJoin = (isGuest ? true : options.joinDefaultChannelsSilenced); return Meteor.call('joinDefaultChannels', silencedJoin); }); } diff --git a/server/methods/getGuestAccount.js b/server/methods/getGuestAccount.js index 779209f4a21c..6f30d176cfd7 100644 --- a/server/methods/getGuestAccount.js +++ b/server/methods/getGuestAccount.js @@ -1,17 +1,28 @@ Meteor.methods({ getGuestAccount: () => { - let guestId = 1; - let lastGuest = RocketChat.models.Users.findOne({guestId: {$gt: 0}}, {sort: {DateTime: -1, limit: 1}}); - if (lastGuest) { - guestId = lastGuest.guestId + 1; + + const guests = RocketChat.models.Users.find( + {username: {$regex: /^anonymous-\d$/}}, + {sort: {guestId: -1}} + ).fetch(); + + let guestId = null, username = 'anonymous-', anonymousCounter = 1; + if (guests) { + // Since we are sorting the results by guestId, the first one + // is always the greatest id + guestId = (guests[0].guestId ? guests[0].guestId + 1 : 1); + anonymousCounter = guests.length + 1; + } else { + guestId = 1; } - let username = 'anonymous-' + guestId; + + username += anonymousCounter; while (RocketChat.models.Users.findOne({ username: username })) { - guestId++; - username = 'anonymous-' + guestId; + anonymousCounter ++; + username = 'anonymous-' + anonymousCounter; } - let userId = Accounts.createUser({ + const userId = Accounts.createUser({ username: username, email: username + '@rocket-chat.guest', password: '', diff --git a/server/startup/removeOfflineGuests.js b/server/startup/removeOfflineGuests.js index 3d598396576d..9fb4ab4082b9 100644 --- a/server/startup/removeOfflineGuests.js +++ b/server/startup/removeOfflineGuests.js @@ -1,11 +1,11 @@ Meteor.startup(() => { - let query = { + const query = { username: {$exists: 1}, status: {$in: ['online', 'away', 'busy']} }; RocketChat.models.Users.find(query).observeChanges({ removed: id => { - let user = RocketChat.models.Users.findOne({_id: id}); + const user = RocketChat.models.Users.findOne({_id: id}); if (user && user.guestId) { RocketChat.models.Users.remove(id); } From 7c06b2a5a813b0314562aaba7d9b58d7acd4e5ec Mon Sep 17 00:00:00 2001 From: Jury Verrigni Date: Sun, 29 Jan 2017 14:29:08 +0000 Subject: [PATCH 5/8] Added prefix and postfix for guests account. Added options to let guests choose their nickname (prepended and appended with postfix and prefix) --- packages/rocketchat-i18n/i18n/en.i18n.json | 3 ++ .../server/methods/setUsername.js | 7 +++++ .../rocketchat-lib/server/models/Users.coffee | 7 +++++ .../server/startup/settings.coffee | 5 ++- .../client/login/form.coffee | 7 +++-- .../client/username/username.coffee | 13 +++++--- server/lib/accounts.js | 8 +++-- server/methods/getGuestAccount.js | 31 +++++++++++-------- 8 files changed, 57 insertions(+), 24 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index f4c3f5bfd1a4..be2b2e6c5faf 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -22,6 +22,9 @@ "Accounts_AllowedDomainsList_Description": "Comma-separated list of allowed domains", "Accounts_AllowEmailChange": "Allow Email Change", "Accounts_AllowGuestAccess": "Allow anonymous/guest access", + "Accounts_GuestNamePostfix": "Guest name postfix", + "Accounts_GuestNamePrefix": "Guest name prefix", + "Accounts_AllowGuestToChooseName": "Allow guests to choose name", "Accounts_AllowPasswordChange": "Allow Password Change", "Accounts_AllowUserAvatarChange": "Allow User Avatar Change", "Accounts_AllowUsernameChange": "Allow Username Change", diff --git a/packages/rocketchat-lib/server/methods/setUsername.js b/packages/rocketchat-lib/server/methods/setUsername.js index b64b1ddc5b3b..6c2f3d181404 100644 --- a/packages/rocketchat-lib/server/methods/setUsername.js +++ b/packages/rocketchat-lib/server/methods/setUsername.js @@ -28,6 +28,13 @@ Meteor.methods({ throw new Meteor.Error('username-invalid', `${_.escape(username)} is not a valid username, use only letters, numbers, dots, hyphens and underscores`); } + const guestPrefix = RocketChat.settings.get('Accounts_GuestNamePrefix'); + const guestPostfix = RocketChat.settings.get('Accounts_GuestNamePostfix'); + + if (user.guestId) { + username = guestPrefix + username + guestPostfix; + } + if (user.username !== undefined) { if (!username.toLowerCase() === user.username.toLowerCase()) { if (!RocketChat.checkUsernameAvailability(username)) { diff --git a/packages/rocketchat-lib/server/models/Users.coffee b/packages/rocketchat-lib/server/models/Users.coffee index f5c6a201f3c1..8f8e08ba2b4e 100644 --- a/packages/rocketchat-lib/server/models/Users.coffee +++ b/packages/rocketchat-lib/server/models/Users.coffee @@ -247,6 +247,13 @@ class ModelUsers extends RocketChat.models._Base return @update _id, update + setGuestId: (_id, guestId) -> + update = + $set: + guestId: guestId + + return @update _id, update + setCustomFields: (_id, fields) -> values = {} for key, value of fields diff --git a/packages/rocketchat-lib/server/startup/settings.coffee b/packages/rocketchat-lib/server/startup/settings.coffee index 87138e2e4769..affed93914d5 100644 --- a/packages/rocketchat-lib/server/startup/settings.coffee +++ b/packages/rocketchat-lib/server/startup/settings.coffee @@ -5,7 +5,10 @@ RocketChat.settings.add('uniqueID', process.env.DEPLOYMENT_ID or Random.id(), { # if you add a node to the i18n.json with the same setting name but with `_Description` it will automatically work. RocketChat.settings.addGroup 'Accounts', -> @add 'Accounts_AllowGuestAccess', false, { type: 'boolean', public: true} - @add 'Accounts_AutomaticallyLoginAsGuest', true, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowGuestAccess', value: true }} + @add 'Accounts_GuestNamePrefix', 'anonymous-', { type: 'string', public: true, enableQuery: { _id: 'Accounts_AllowGuestAccess', value: true } } + @add 'Accounts_GuestNamePostfix', '', { type: 'string', public: true, enableQuery: { _id: 'Accounts_AllowGuestAccess', value: true } } + @add 'Accounts_AllowGuestToChooseName', true, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowGuestAccess', value: true } } + @add 'Accounts_AutomaticallyLoginAsGuest', true, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowGuestAccess', value: true } } @add 'Accounts_AllowDeleteOwnAccount', false, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowUserProfileChange', value: true } } @add 'Accounts_AllowUserProfileChange', true, { type: 'boolean', public: true } @add 'Accounts_AllowUserAvatarChange', true, { type: 'boolean', public: true } diff --git a/packages/rocketchat-ui-login/client/login/form.coffee b/packages/rocketchat-ui-login/client/login/form.coffee index f438d0962915..0ae44cd62e35 100644 --- a/packages/rocketchat-ui-login/client/login/form.coffee +++ b/packages/rocketchat-ui-login/client/login/form.coffee @@ -132,11 +132,12 @@ Template.loginForm.events RocketChat.callbacks.run('loginPageStateChange', Template.instance().state.get()); 'click .login-as-guest': -> - Meteor.call 'getGuestAccount', (error, user) -> + Meteor.call 'getGuestAccount', (error, email) -> if error - console.log (error); + console.log error return - Meteor.loginWithPassword(user, ''); + Meteor.loginWithPassword email, '', (error) -> + console.log error 'click .one-passsword': -> if not OnePassword?.findLoginForUrl? diff --git a/packages/rocketchat-ui-login/client/username/username.coffee b/packages/rocketchat-ui-login/client/username/username.coffee index 225d190b79cb..0d43c720c665 100644 --- a/packages/rocketchat-ui-login/client/username/username.coffee +++ b/packages/rocketchat-ui-login/client/username/username.coffee @@ -2,12 +2,17 @@ Template.username.onCreated -> self = this self.username = new ReactiveVar - Meteor.call 'getUsernameSuggestion', (error, username) -> + if Meteor.user().guestId self.username.set ready: true - username: username - Meteor.defer -> - self.find('input').focus() + username: '' + else + Meteor.call 'getUsernameSuggestion', (error, username) -> + self.username.set + ready: true + username: username + Meteor.defer -> + self.find('input').focus() Template.username.helpers username: -> diff --git a/server/lib/accounts.js b/server/lib/accounts.js index aa0c056a8d3e..fc17e1ec722d 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -112,7 +112,7 @@ Accounts.insertUserDoc = _.wrap(Accounts.insertUserDoc, function(insertUserDoc, _id: _id }); - const isGuest = user.username && user.username.match(/guest-\d/); + const isGuest = user.emails[0] && user.emails[0].address.match(/@rocket-chat\.guest/); if (user.username && options.joinDefaultChannels !== false && user.joinDefaultChannels !== false) { Meteor.runAsUser(_id, function() { @@ -133,13 +133,15 @@ Accounts.insertUserDoc = _.wrap(Accounts.insertUserDoc, function(insertUserDoc, if (hasAdmin) { roles.push('user'); - } else if (isGuest) { - roles.push('guest'); } else { roles.push('admin'); } } + if (isGuest) { + roles = ['guest']; + } + RocketChat.authz.addUserRoles(_id, roles); return _id; diff --git a/server/methods/getGuestAccount.js b/server/methods/getGuestAccount.js index 6f30d176cfd7..94426c34f9e9 100644 --- a/server/methods/getGuestAccount.js +++ b/server/methods/getGuestAccount.js @@ -1,13 +1,18 @@ Meteor.methods({ getGuestAccount: () => { + const guestPrefix = RocketChat.settings.get('Accounts_GuestNamePrefix'); + const guestPostfix = RocketChat.settings.get('Accounts_GuestNamePostfix'); const guests = RocketChat.models.Users.find( - {username: {$regex: /^anonymous-\d$/}}, + { + username: {$regex: new RegExp(guestPrefix + '\d' + guestPostfix, 'i')}, + guestId: {$exists: true} + }, {sort: {guestId: -1}} ).fetch(); - let guestId = null, username = 'anonymous-', anonymousCounter = 1; - if (guests) { + let guestId = null, username = guestPrefix, anonymousCounter = 1; + if (!_.isEmpty(guests)) { // Since we are sorting the results by guestId, the first one // is always the greatest id guestId = (guests[0].guestId ? guests[0].guestId + 1 : 1); @@ -16,23 +21,23 @@ Meteor.methods({ guestId = 1; } - username += anonymousCounter; - while (RocketChat.models.Users.findOne({ username: username })) { + username += anonymousCounter + guestPostfix; + while (RocketChat.models.Users.findOne({ name: username })) { anonymousCounter ++; - username = 'anonymous-' + anonymousCounter; + username = guestPrefix + anonymousCounter + guestPostfix; } + const email = username + '@rocket-chat.guest'; + const userId = Accounts.createUser({ - username: username, - email: username + '@rocket-chat.guest', - password: '', - profile: {name: username} + email: email, + password: '' }); + RocketChat.models.Users.setName(userId, username); + RocketChat.models.Users.setGuestId(userId, guestId); Accounts.setPassword(userId, ''); - RocketChat.models.Users.update(userId, {$set: {guestId: guestId}}); - - return username; + return email; } }); From fdb7365dcc644e1e2b57e67335c635a61d9988b8 Mon Sep 17 00:00:00 2001 From: Jury Verrigni Date: Tue, 7 Feb 2017 14:34:03 +0000 Subject: [PATCH 6/8] Guest account cannot be set as moderator, cannot receive/do video calls and fixed allow guest to choose name --- .../client/views/app/tabbar/visitorInfo.html | 34 +++--- .../client/views/app/tabbar/visitorInfo.js | 8 ++ .../flex-tab/tabs/userInfo.coffee | 6 + .../flex-tab/tabs/userInfo.html | 105 +++++++++--------- .../client/vrecord.coffee | 9 +- server/methods/getGuestAccount.js | 3 + server/publications/activeUsers.js | 3 +- 7 files changed, 96 insertions(+), 72 deletions(-) diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html index 21e6041d869d..0c785ea23b87 100644 --- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html +++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html @@ -8,23 +8,25 @@ {{/if}}
- {{#with user}} -
-

{{username}}

-

{{name}}

+ {{#unless isGuest}} + {{#with user}} +
+

{{username}}

+

{{name}}

-
    - {{#if utc}}
  • {{userTime}} (UTC {{utc}})
  • {{/if}} - {{#each visitorEmails}}
  • {{address}}{{#if verified}} {{/if}}
  • {{/each}} - {{#each phone}}
  • {{phoneNumber}}
  • {{/each}} - {{#if lastLogin}}
  • {{_ "Created_at"}}: {{createdAt}}
  • {{/if}} - {{#if lastLogin}}
  • {{_ "Last_login"}}: {{lastLogin}}
  • {{/if}} - {{#if ip}}
  • {{ip}}
  • {{/if}} - {{#if os}}
  • {{os}}
  • {{/if}} - {{#if browser}}
  • {{browser}}
  • {{/if}} -
-
- {{/with}} +
    + {{#if utc}}
  • {{userTime}} (UTC {{utc}})
  • {{/if}} + {{#each visitorEmails}}
  • {{address}}{{#if verified}} {{/if}}
  • {{/each}} + {{#each phone}}
  • {{phoneNumber}}
  • {{/each}} + {{#if lastLogin}}
  • {{_ "Created_at"}}: {{createdAt}}
  • {{/if}} + {{#if lastLogin}}
  • {{_ "Last_login"}}: {{lastLogin}}
  • {{/if}} + {{#if ip}}
  • {{ip}}
  • {{/if}} + {{#if os}}
  • {{os}}
  • {{/if}} + {{#if browser}}
  • {{browser}}
  • {{/if}} +
+
+ {{/with}} + {{/unless}} {{#with room}}
diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.js b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.js index 3ee2edc3c034..e86b95f137c2 100644 --- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.js +++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.js @@ -29,6 +29,14 @@ Template.visitorInfo.helpers({ return this.tags && this.tags.join(', '); }, + isGuest() { + const user = Template.instance().user.get(); + if (user) { + return user.guestId || Meteor.user().guestId; + } + return false; + }, + customFields() { const fields = []; let livechatData = {}; diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee index 8759f6c5a8f7..ec58ac5c5d53 100644 --- a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee +++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee @@ -10,6 +10,12 @@ Template.userInfo.helpers user = Template.instance().user.get() return user.username + isGuest: -> + user = Template.instance().user.get() + if user + return user.guestId or Meteor.user().guestId + return false + email: -> user = Template.instance().user.get() return user.emails?[0]?.address diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html index 4d31d1bb69e9..90edbfa4e02b 100644 --- a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html +++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html @@ -41,69 +41,70 @@

{{username}}

{{/with}}