[NEW] Option to allow to signup as anonymous

pull/6797/head
Rodrigo Nascimento 8 years ago
parent 1ced54e6a8
commit cfe5068fec
  1. 2
      packages/rocketchat-authorization/server/functions/canAccessRoom.js
  2. 13
      packages/rocketchat-authorization/server/startup.js
  3. 7
      packages/rocketchat-i18n/i18n/en.i18n.json
  4. 2
      packages/rocketchat-lib/client/lib/openRoom.coffee
  5. 2
      packages/rocketchat-lib/server/methods/getRoomRoles.js
  6. 15
      packages/rocketchat-lib/server/startup/settings.js
  7. 2
      packages/rocketchat-lib/startup/defaultRoomTypes.js
  8. 4
      packages/rocketchat-ui-master/client/main.js
  9. 16
      packages/rocketchat-ui-message/client/messageBox.coffee
  10. 7
      packages/rocketchat-ui-message/client/messageBox.html
  11. 4
      packages/rocketchat-ui-sidenav/client/accountBox.js
  12. 1
      packages/rocketchat-ui/client/lib/accounts.js
  13. 2
      packages/rocketchat-ui/client/lib/collections.js
  14. 2
      packages/rocketchat-ui/client/views/app/room.coffee
  15. 20
      server/methods/afterVerifyEmail.js
  16. 2
      server/methods/canAccessRoom.js
  17. 2
      server/methods/getUsernameSuggestion.js
  18. 4
      server/methods/loadHistory.js
  19. 14
      server/methods/registerUser.js
  20. 24
      server/methods/saveUserProfile.js
  21. 4
      server/publications/room.js
  22. 2
      server/publications/spotlight.js
  23. 12
      server/startup/migrations/v093.js

@ -2,7 +2,7 @@
RocketChat.authz.roomAccessValidators = [
function(room, user = {}) {
if (room.t === 'c') {
if (!user._id && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true) {
if (!user._id && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) {
return true;
}

@ -46,20 +46,20 @@ Meteor.startup(function() {
{ _id: 'set-moderator', roles : ['admin', 'owner'] },
{ _id: 'set-owner', roles : ['admin', 'owner'] },
{ _id: 'unarchive-room', roles : ['admin'] },
{ _id: 'view-c-room', roles : ['admin', 'user', 'bot'] },
{ _id: 'view-d-room', roles : ['admin', 'user', 'bot'] },
{ _id: 'view-c-room', roles : ['admin', 'user', 'bot', 'anonymous'] },
{ _id: 'view-d-room', roles : ['admin', 'user', 'bot', 'anonymous'] },
{ _id: 'view-full-other-user-info', roles : ['admin'] },
{ _id: 'view-history', roles : ['admin', 'user'] },
{ _id: 'view-history', roles : ['admin', 'user', 'anonymous'] },
{ _id: 'view-joined-room', roles : ['guest', 'bot'] },
{ _id: 'view-join-code', roles : ['admin'] },
{ _id: 'view-logs', roles : ['admin'] },
{ _id: 'view-other-user-channels', roles : ['admin'] },
{ _id: 'view-p-room', roles : ['admin', 'user'] },
{ _id: 'view-p-room', roles : ['admin', 'user', 'anonymous'] },
{ _id: 'view-privileged-setting', roles : ['admin'] },
{ _id: 'view-room-administration', roles : ['admin'] },
{ _id: 'view-statistics', roles : ['admin'] },
{ _id: 'view-user-administration', roles : ['admin'] },
{ _id: 'preview-c-room', roles : ['admin', 'user'] }
{ _id: 'preview-c-room', roles : ['admin', 'user', 'anonymous'] }
];
for (const permission of permissions) {
@ -74,7 +74,8 @@ Meteor.startup(function() {
{ name: 'owner', scope: 'Subscriptions', description: 'Owner' },
{ name: 'user', scope: 'Users', description: '' },
{ name: 'bot', scope: 'Users', description: '' },
{ name: 'guest', scope: 'Users', description: '' }
{ name: 'guest', scope: 'Users', description: '' },
{ name: 'anonymous', scope: 'Users', description: '' }
];
for (const role of defaultRoles) {

@ -17,7 +17,8 @@
"Accessing_permissions": "Accessing permissions",
"Account_SID": "Account SID",
"Accounts": "Accounts",
"Accounts_AllowAnonymousAccess": "Allow anonymous access",
"Accounts_AllowAnonymousRead": "Allow anonymous read",
"Accounts_AllowAnonymousWrite": "Allow anonymous write",
"Accounts_AllowDeleteOwnAccount": "Allow users to delete own account",
"Accounts_AllowedDomainsList": "Allowed Domains List",
"Accounts_AllowedDomainsList_Description": "Comma-separated list of allowed domains",
@ -35,6 +36,7 @@
"Accounts_BlockedUsernameList": "Blocked Username List",
"Accounts_BlockedUsernameList_Description": "Comma-separated list of blocked usernames (case-insensitive)",
"Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:<br/><code>{\n\"role\": {\n\"type\": \"select\",\n\"defaultValue\": \"student\",\n\"options\": [\"teacher\", \"student\"],\n\"required\": true,\n\"modifyRecordField\": {\n\"array\": true,\n\"field\": \"roles\"\n}\n},\n\"twitter\": {\n\"type\": \"text\",\n\"required\": true,\n\"minLength\": 2,\n\"maxLength\": 10\n}\n}</code> ",
"Accounts_DefaultUsernamePrefixSuggestion": "Default username prefix suggestion",
"Accounts_denyUnverifiedEmail": "Deny unverified email",
"Accounts_EmailVerification": "Email Verification",
"Accounts_EmailVerification_Description": "Make sure you have correct SMTP settings to use this feature",
@ -1124,6 +1126,7 @@
"or": "or",
"Open_your_authentication_app_and_enter_the_code": "Open your authentication app and enter the code. You can also use one of your backup codes.",
"Order": "Order",
"Or_talk_as_anonymous": "Or talk as anonymous",
"OS_Arch": "OS Arch",
"OS_Cpus": "OS CPU Count",
"OS_Freemem": "OS Free Memory",
@ -1228,7 +1231,6 @@
"Register": "Register a new account",
"Registration": "Registration",
"Registration_Succeeded": "Registration Succeeded",
"Register_or_login_to_send_messages": "Register or login to send messages",
"Registration_via_Admin": "Registration via Admin",
"Regular_Expressions": "Regular Expressions",
"Release": "Release",
@ -1363,6 +1365,7 @@
"Showing_archived_results": "<p>Showing <b>%s</b> archived results</p>",
"Showing_online_users": "Showing: <b>__total_showing__</b>, Online: __online__, Total: __total__ users",
"Showing_results": "<p>Showing <b>%s</b> results</p>",
"Sign_in_to_start_talking": "Sign in to start talking",
"since_creation": "since %s",
"Site_Name": "Site Name",
"Site_Url": "Site URL",

@ -6,7 +6,7 @@ currentTracker = undefined
Meteor.defer ->
currentTracker = Tracker.autorun (c) ->
user = Meteor.user()
if (user? and not user.username?) or (not user? and RocketChat.settings.get('Accounts_AllowAnonymousAccess') is false)
if (user? and not user.username?) or (not user? and RocketChat.settings.get('Accounts_AllowAnonymousRead') is false)
BlazeLayout.render 'main'
return

@ -3,7 +3,7 @@ Meteor.methods({
check(rid, String);
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === false) {
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomRoles' });
}

@ -8,10 +8,18 @@ RocketChat.settings.add('uniqueID', process.env.DEPLOYMENT_ID || 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', function() {
this.add('Accounts_AllowAnonymousAccess', false, {
this.add('Accounts_AllowAnonymousRead', false, {
type: 'boolean',
public: true
});
this.add('Accounts_AllowAnonymousWrite', false, {
type: 'boolean',
public: true,
enableQuery: {
_id: 'Accounts_AllowAnonymousRead',
value: true
}
});
this.add('Accounts_AllowDeleteOwnAccount', false, {
type: 'boolean',
'public': true,
@ -62,7 +70,11 @@ RocketChat.settings.addGroup('Accounts', function() {
type: 'boolean',
'public': true
});
this.section('Registration', function() {
this.add('Accounts_DefaultUsernamePrefixSuggestion', 'user', {
type: 'string'
});
this.add('Accounts_RequireNameForSignUp', true, {
type: 'boolean',
'public': true
@ -145,6 +157,7 @@ RocketChat.settings.addGroup('Accounts', function() {
i18nLabel: 'Custom_Fields'
});
});
this.section('Avatar', function() {
this.add('Accounts_AvatarResize', true, {
type: 'boolean'

@ -28,7 +28,7 @@ RocketChat.roomTypes.add('c', 10, {
},
condition() {
return RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true;
return RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || RocketChat.settings.get('Accounts_AllowAnonymousRead') === true;
},
showJoinLink(roomId) {

@ -110,7 +110,7 @@ Template.main.helpers({
return RocketChat.settings.get('Site_Name');
},
logged() {
if (Meteor.userId() != null || (RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true && Session.get('forceLogin') !== true)) {
if (Meteor.userId() != null || (RocketChat.settings.get('Accounts_AllowAnonymousRead') === true && Session.get('forceLogin') !== true)) {
$('html').addClass('noscroll').removeClass('scroll');
return true;
} else {
@ -134,7 +134,7 @@ Template.main.helpers({
return ready;
},
hasUsername() {
return (Meteor.userId() != null && Meteor.user().username != null) || (Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true);
return (Meteor.userId() != null && Meteor.user().username != null) || (Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true);
},
requirePasswordChange() {
const user = Meteor.user();

@ -124,8 +124,11 @@ Template.messageBox.helpers
showSandstorm: ->
return Meteor.settings.public.sandstorm && !Meteor.isCordova
isAnonymous: ->
return not Meteor.userId()? and RocketChat.settings.get('Accounts_AllowAnonymousAccess') is true
anonymousRead: ->
return not Meteor.userId()? and RocketChat.settings.get('Accounts_AllowAnonymousRead') is true
anonymousWrite: ->
return not Meteor.userId()? and RocketChat.settings.get('Accounts_AllowAnonymousRead') is true and RocketChat.settings.get('Accounts_AllowAnonymousWrite') is true
firefoxPasteUpload = (fn) ->
user = navigator.userAgent.match(/Firefox\/(\d+)\.\d/)
@ -186,6 +189,15 @@ Template.messageBox.events
event.preventDefault()
Session.set('forceLogin', true)
'click .register-anonymous': (event) ->
event.stopPropagation()
event.preventDefault()
Meteor.call 'registerUser', {}, (error, loginData) ->
if loginData && loginData.token
Meteor.loginWithToken loginData.token
'focus .input-message': (event, instance) ->
KonchatNotification.removeRoomNotification @_id
chatMessages[@_id].input = instance.find('.input-message')

@ -143,9 +143,12 @@
<button class="button join"><span><i class="icon-login"></i> {{_ "join"}}</span></button>
</div>
{{/if}}
{{#if isAnonymous}}
{{#if anonymousRead}}
<div>
<button class="button register"><span><i class="icon-login"></i> {{_ "Register_or_login_to_send_messages"}}</span></button>
<button class="button register"><span>{{_ "Sign_in_to_start_talking"}}</span></button>
{{#if anonymousWrite}}
<button class="button register-anonymous"><span>{{_ "Or_talk_as_anonymous"}}</span></button>
{{/if}}
</div>
{{/if}}
{{/with}}

@ -1,6 +1,6 @@
Template.accountBox.helpers({
myUserInfo() {
if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousAccess')) {
if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
return {
name: t('Anonymous'),
status: 'online',
@ -50,7 +50,7 @@ Template.accountBox.events({
},
'click .account-box'() {
if (Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousAccess')) {
if (Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
return;
}

@ -3,6 +3,7 @@ Accounts.onEmailVerificationLink(function(token, done) {
Accounts.verifyEmail(token, function(error) {
if (error == null) {
toastr.success(t('Email_verified'));
Meteor.call('afterVerifyEmail');
}
return done();
});

@ -17,7 +17,7 @@ RocketChat.models.Messages = _.extend({}, RocketChat.models.Messages, this.ChatM
Meteor.startup(() => {
Tracker.autorun(() => {
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true) {
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) {
this.CachedChatRoom.init();
this.CachedChatSubscription.ready.set(true);
}

@ -181,7 +181,7 @@ Template.room.helpers
if room.t isnt 'c'
return true
if RocketChat.settings.get('Accounts_AllowAnonymousAccess') is true
if RocketChat.settings.get('Accounts_AllowAnonymousRead') is true
return true
if RocketChat.authz.hasAllPermission('preview-c-room')

@ -0,0 +1,20 @@
Meteor.methods({
afterVerifyEmail() {
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'afterVerifyEmail'
});
}
const user = RocketChat.models.Users.findOneById(userId);
const verifiedEmail = _.find(user.emails, (email) => email.verified);
if (verifiedEmail) {
RocketChat.models.Roles.addUserRoles(user._id, 'user');
RocketChat.models.Roles.removeUserRoles(user._id, 'anonymous');
}
}
});

@ -5,7 +5,7 @@ Meteor.methods({
let user;
if (!userId && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === false) {
if (!userId && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'canAccessRoom'
});

@ -92,7 +92,7 @@ function generateSuggestion(user) {
}
if (usernames.length === 0 || usernames[0].length === 0) {
usernames.push('user');
usernames.push(RocketChat.settings.get('Accounts_DefaultUsernamePrefixSuggestion'));
}
let index = 0;

@ -21,7 +21,7 @@ Meteor.methods({
loadHistory(rid, end, limit = 20, ls) {
check(rid, String);
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === false) {
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'loadHistory'
});
@ -34,7 +34,7 @@ Meteor.methods({
return false;
}
const canAnonymous = RocketChat.settings.get('Accounts_AllowAnonymousAccess');
const canAnonymous = RocketChat.settings.get('Accounts_AllowAnonymousRead');
const canPreview = RocketChat.authz.hasPermission(fromId, 'preview-c-room');
if (room.t === 'c' && !canAnonymous && !canPreview && room.usernames.indexOf(room.username) === -1) {
return false;

@ -1,11 +1,25 @@
Meteor.methods({
registerUser(formData) {
const AllowAnonymousRead = RocketChat.settings.get('Accounts_AllowAnonymousRead');
const AllowAnonymousWrite = RocketChat.settings.get('Accounts_AllowAnonymousWrite');
if (AllowAnonymousRead === true && AllowAnonymousWrite === true && formData.email == null) {
const userId = Accounts.insertUserDoc({}, {
globalRoles: [
'anonymous'
]
});
const { id, token } = Accounts._loginUser(this, userId);
return { id, token };
} else {
check(formData, Match.ObjectIncluding({
email: String,
pass: String,
name: String,
secretURL: Match.Optional(String)
}));
}
if (RocketChat.settings.get('Accounts_RegistrationForm') === 'Disabled') {
throw new Meteor.Error('error-user-registration-disabled', 'User registration is disabled', { method: 'registerUser' });

@ -31,17 +31,6 @@ Meteor.methods({
}
return true;
}
if ((settings.newPassword) && RocketChat.settings.get('Accounts_AllowPasswordChange') === true) {
if (!checkPassword(user, settings.typedPassword)) {
throw new Meteor.Error('error-invalid-password', 'Invalid password', {
method: 'saveUserProfile'
});
}
Accounts.setPassword(Meteor.userId(), settings.newPassword, {
logout: false
});
}
if (settings.realname) {
RocketChat.setRealName(Meteor.userId(), settings.realname);
@ -61,6 +50,19 @@ Meteor.methods({
Meteor.call('setEmail', settings.email);
}
// Should be the last chack to prevent error when trying to check password for users without password
if ((settings.newPassword) && RocketChat.settings.get('Accounts_AllowPasswordChange') === true) {
if (!checkPassword(user, settings.typedPassword)) {
throw new Meteor.Error('error-invalid-password', 'Invalid password', {
method: 'saveUserProfile'
});
}
Accounts.setPassword(Meteor.userId(), settings.newPassword, {
logout: false
});
}
RocketChat.models.Users.setProfile(Meteor.userId(), {});
RocketChat.saveCustomFields(Meteor.userId(), customFields);

@ -40,7 +40,7 @@ const roomMap = (record) => {
Meteor.methods({
'rooms/get'(updatedAt) {
if (!Meteor.userId()) {
if (RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true) {
if (RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) {
return RocketChat.models.Rooms.findByDefaultAndTypes(true, ['c'], options).fetch();
}
return [];
@ -59,7 +59,7 @@ Meteor.methods({
},
getRoomByTypeAndName(type, name) {
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === false) {
if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomByTypeAndName' });
}

@ -19,7 +19,7 @@ Meteor.methods({
const regex = new RegExp(s.trim(s.escapeRegExp(text)), 'i');
if (this.userId == null) {
if (RocketChat.settings.get('Accounts_AllowAnonymousAccess') === true) {
if (RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) {
result.rooms = RocketChat.models.Rooms.findByNameAndTypeNotDefault(regex, 'c', roomOptions).fetch();
}
return result;

@ -0,0 +1,12 @@
RocketChat.Migrations.add({
version: 93,
up() {
if (RocketChat && RocketChat.models && RocketChat.models.Settings) {
const setting = RocketChat.models.Settings.findOne({ _id: 'Accounts_AllowAnonymousAccess' });
if (setting && setting.value === true) {
RocketChat.models.Settings.update({ _id: 'Accounts_AllowAnonymousRead' }, { $set: { value: setting.value } });
}
}
}
});
Loading…
Cancel
Save