From 09eb833a79b069da9b6c07c6486cc8726b2d3f2f Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Wed, 22 Feb 2017 15:46:46 -0300 Subject: [PATCH] Add permissions; Fixed bugs; --- .../client/lib/actionButton.js | 65 ++++++-------- .../client/lib/autotranslate.js | 4 +- .../client/lib/tabBar.js | 2 +- .../client/stylesheets/autotranslate.less | 3 +- .../client/views/autoTranslateFlexTab.html | 84 ++++++++++--------- .../client/views/autoTranslateFlexTab.js | 6 ++ packages/rocketchat-autotranslate/package.js | 1 + .../server/autotranslate.js | 2 +- .../server/methods/getSupportedLanguages.js | 4 + .../server/methods/saveSettings.js | 4 + .../server/models/Subscriptions.js | 3 +- .../server/permissions.js | 5 ++ packages/rocketchat-i18n/i18n/en.i18n.json | 1 + .../client/vendor/fontello/css/fontello.css | 20 ++--- .../message/message.coffee | 5 +- 15 files changed, 111 insertions(+), 98 deletions(-) create mode 100644 packages/rocketchat-autotranslate/server/permissions.js diff --git a/packages/rocketchat-autotranslate/client/lib/actionButton.js b/packages/rocketchat-autotranslate/client/lib/actionButton.js index 8ba488f696c..869e1801e06 100644 --- a/packages/rocketchat-autotranslate/client/lib/actionButton.js +++ b/packages/rocketchat-autotranslate/client/lib/actionButton.js @@ -1,43 +1,32 @@ Meteor.startup(function() { - RocketChat.MessageAction.addButton({ - id: 'show-original-message', - icon: 'icon-language', - i18nLabel: 'Show_original_message', - context: [ - 'message', - 'message-mobile' - ], - action() { - const message = this._arguments[1]; - RocketChat.MessageAction.hideDropDown(); - RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateShowOriginal: true } }); - }, + Tracker.autorun(function() { + if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) { + RocketChat.MessageAction.addButton({ + id: 'toggle-language', + icon: 'icon-language', + i18nLabel: 'Toggle_original_translated', + context: [ + 'message', + 'message-mobile' + ], + action() { + const message = this._arguments[1]; + RocketChat.MessageAction.hideDropDown(); + if (message.autoTranslateShowInverse) { + RocketChat.models.Messages.update({ _id: message._id }, { $unset: { autoTranslateShowInverse: true } }); + } else { + RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateShowInverse: true } }); + } + }, - validation(message) { - return message && !message.autoTranslateShowOriginal && message.u && message.u._id !== Meteor.userId(); - }, + validation(message) { + return message && message.u && message.u._id !== Meteor.userId(); + }, - order: 90 - }); - - RocketChat.MessageAction.addButton({ - id: 'show-translated-message', - icon: 'icon-language', - i18nLabel: 'Show_translated_message', - context: [ - 'message', - 'message-mobile' - ], - action() { - const message = this._arguments[1]; - RocketChat.MessageAction.hideDropDown(); - RocketChat.models.Messages.update({ _id: message._id }, { $unset: { autoTranslateShowOriginal: 1 } }); - }, - - validation(message) { - return message && message.autoTranslateShowOriginal && message.u && message.u._id !== Meteor.userId(); - }, - - order: 90 + order: 90 + }); + } else { + RocketChat.MessageAction.removeButton('toggle-language'); + } }); }); diff --git a/packages/rocketchat-autotranslate/client/lib/autotranslate.js b/packages/rocketchat-autotranslate/client/lib/autotranslate.js index d20bc790cbe..84c1028981d 100644 --- a/packages/rocketchat-autotranslate/client/lib/autotranslate.js +++ b/packages/rocketchat-autotranslate/client/lib/autotranslate.js @@ -1,10 +1,10 @@ Meteor.startup(function() { Tracker.autorun(function() { - if (RocketChat.settings.get('AutoTranslate_Enabled')) { + if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) { RocketChat.callbacks.add('renderMessage', (message) => { if (message.u._id !== Meteor.userId()) { const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); - if (subscription && subscription.autoTranslate === true && subscription.autoTranslateDisplay === true && subscription.autoTranslateLanguage && !message.autoTranslateShowOriginal) { + if (subscription && subscription.autoTranslate === true && subscription.autoTranslateLanguage && !!subscription.autoTranslateDisplay !== !!message.autoTranslateShowInverse) { const autoTranslateLanguage = subscription.autoTranslateLanguage; if (!message.translations) { message.translations = {}; diff --git a/packages/rocketchat-autotranslate/client/lib/tabBar.js b/packages/rocketchat-autotranslate/client/lib/tabBar.js index 74f40296aff..53819c7f000 100644 --- a/packages/rocketchat-autotranslate/client/lib/tabBar.js +++ b/packages/rocketchat-autotranslate/client/lib/tabBar.js @@ -1,6 +1,6 @@ Meteor.startup(function() { Tracker.autorun(function() { - if (RocketChat.settings.get('AutoTranslate_Enabled')) { + if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) { RocketChat.TabBar.addButton({ groups: ['channel', 'group', 'direct'], id: 'autotranslate', diff --git a/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less b/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less index 407d508311a..8982744481d 100644 --- a/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less +++ b/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less @@ -34,8 +34,7 @@ } } -.message { - +.message { .translated { border-left: 1px dotted; padding-left: 3px; diff --git a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html index fab8d0d2a23..1852591f12e 100644 --- a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html +++ b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html @@ -1,51 +1,53 @@ diff --git a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js index 43c6970d43d..1d192eb844a 100644 --- a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js +++ b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js @@ -106,6 +106,12 @@ Template.autoTranslateFlexTab.onCreated(function() { if (err) { return handleError(err); } + + // Update all visible messages to reflect this setting + if (field === 'autoTranslate' || field === 'autoTranslateDisplay') { + RocketChat.models.Messages.update({ rid: Session.get('openedRoom') }, { $unset: { autoTranslateShowInverse: 1 }, $set: { random: Random.id() } }, { multi: true }); + } + this.editing.set(); }); } diff --git a/packages/rocketchat-autotranslate/package.js b/packages/rocketchat-autotranslate/package.js index 00385ab8375..e4a5eee2b03 100644 --- a/packages/rocketchat-autotranslate/package.js +++ b/packages/rocketchat-autotranslate/package.js @@ -27,6 +27,7 @@ Package.onUse(function(api) { api.addFiles([ 'server/settings.js', 'server/autotranslate.js', + 'server/permissions.js', 'server/models/Messages.js', 'server/models/Subscriptions.js', 'server/methods/saveSettings.js', diff --git a/packages/rocketchat-autotranslate/server/autotranslate.js b/packages/rocketchat-autotranslate/server/autotranslate.js index 8aaa7cc5897..a757ab97a01 100644 --- a/packages/rocketchat-autotranslate/server/autotranslate.js +++ b/packages/rocketchat-autotranslate/server/autotranslate.js @@ -68,7 +68,7 @@ class AutoTranslate { if (this.enabled && this.apiKey && message.msg) { Meteor.defer(() => { const translations = {}; - const targetLanguages = RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoom(room._id); + const targetLanguages = RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoomAndNotUser(room._id, message.u && message.u._id); message.html = s.escapeHTML(String(message.msg)); message = this.tokenize(message); diff --git a/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js b/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js index 452d760a22c..841a30268f8 100644 --- a/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js +++ b/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js @@ -1,5 +1,9 @@ Meteor.methods({ 'autoTranslate.getSupportedLanguages'(targetLanguage) { + if (!RocketChat.authz.hasPermission(Meteor.userId(), 'auto-translate')) { + throw new Meteor.Error('error-action-now-allowed', 'Auto-Translate is not allowed', { method: 'autoTranslate.saveSettings'}); + } + return RocketChat.AutoTranslate.getSupportedLanguages(targetLanguage); } }); diff --git a/packages/rocketchat-autotranslate/server/methods/saveSettings.js b/packages/rocketchat-autotranslate/server/methods/saveSettings.js index c1a863e5589..026ea1cda70 100644 --- a/packages/rocketchat-autotranslate/server/methods/saveSettings.js +++ b/packages/rocketchat-autotranslate/server/methods/saveSettings.js @@ -4,6 +4,10 @@ Meteor.methods({ throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'saveAutoTranslateSettings' }); } + if (!RocketChat.authz.hasPermission(Meteor.userId(), 'auto-translate')) { + throw new Meteor.Error('error-action-now-allowed', 'Auto-Translate is not allowed', { method: 'autoTranslate.saveSettings'}); + } + check(rid, String); check(field, String); check(value, String); diff --git a/packages/rocketchat-autotranslate/server/models/Subscriptions.js b/packages/rocketchat-autotranslate/server/models/Subscriptions.js index 6186d8748d1..86405396303 100644 --- a/packages/rocketchat-autotranslate/server/models/Subscriptions.js +++ b/packages/rocketchat-autotranslate/server/models/Subscriptions.js @@ -57,11 +57,12 @@ RocketChat.models.Subscriptions.updateAutoTranslateDisplayById = function(_id, a return this.update(query, update); }; -RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoom = function(rid) { +RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoomAndNotUser = function(rid, userId) { const subscriptionsRaw = RocketChat.models.Subscriptions.model.rawCollection(); const distinct = Meteor.wrapAsync(subscriptionsRaw.distinct, subscriptionsRaw); const query = { rid: rid, + 'u._id': { $ne: userId }, autoTranslate: true }; return distinct('autoTranslateLanguage', query); diff --git a/packages/rocketchat-autotranslate/server/permissions.js b/packages/rocketchat-autotranslate/server/permissions.js new file mode 100644 index 00000000000..207021c014c --- /dev/null +++ b/packages/rocketchat-autotranslate/server/permissions.js @@ -0,0 +1,5 @@ +Meteor.startup(() => { + if (RocketChat.models && RocketChat.models.Permissions) { + RocketChat.models.Permissions.createOrUpdate('auto-translate', ['admin']); + } +}); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 14ca4c56686..6d58d412718 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1475,6 +1475,7 @@ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "To install Rocket.Chat Livechat in your website, copy & paste this code above the last </body> tag on your site.", "to_see_more_details_on_how_to_integrate": "to see more details on how to integrate.", "To_users": "To Users", + "Toggle_original_translated": "Toggle original/translated", "Topic": "Topic", "Travel_and_Places": "Travel & Places", "Transcript_Enabled": "Ask visitor if they would like a transcript after chat closed", diff --git a/packages/rocketchat-theme/client/vendor/fontello/css/fontello.css b/packages/rocketchat-theme/client/vendor/fontello/css/fontello.css index f342a06f8e9..2cc826d5407 100755 --- a/packages/rocketchat-theme/client/vendor/fontello/css/fontello.css +++ b/packages/rocketchat-theme/client/vendor/fontello/css/fontello.css @@ -19,42 +19,42 @@ } } */ - + [class^="icon-"]:before, [class*=" icon-"]:before { font-family: "fontello"; font-style: normal; font-weight: normal; speak: none; - + display: inline-block; text-decoration: inherit; width: 1em; margin-right: .2em; text-align: center; /* opacity: .8; */ - + /* For safety - reset parent styles, that can break glyph codes*/ font-variant: normal; text-transform: none; - + /* fix buttons height, for twitter bootstrap */ line-height: 1em; - + /* Animation center compensation - margins should be symmetric */ /* remove if not needed */ margin-left: .2em; - + /* you can be more comfortable with increased icons size */ /* font-size: 120%; */ - + /* Font smoothing. That was taken from TWBS */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - + /* Uncomment for 3D effect */ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } - + .icon-parking:before { content: '\21'; } /* '!' */ .icon-bedroom:before { content: '\22'; } /* '"' */ .icon-elevator:before { content: '\23'; } /* '#' */ @@ -540,4 +540,4 @@ .icon-no-newline:before { content: '\e98d'; } /* '' */ .icon-tools:before { content: '\e98e'; } /* '' */ .icon-tape:before { content: '\e98f'; } /* '' */ -.icon-language:before { content: '\f1ab'; } /* '' */ \ No newline at end of file +.icon-language:before { content: '\f1ab'; } /* '' */ diff --git a/packages/rocketchat-ui-message/message/message.coffee b/packages/rocketchat-ui-message/message/message.coffee index b433f7a8d93..306ddb3f0ce 100644 --- a/packages/rocketchat-ui-message/message/message.coffee +++ b/packages/rocketchat-ui-message/message/message.coffee @@ -40,8 +40,9 @@ Template.message.helpers return 'system' showTranslated: -> - subscription = RocketChat.models.Subscriptions.findOne({ rid: Session.get('openedRoom') }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); - return this.u?._id isnt Meteor.userId() and not this.autoTranslateShowOriginal and subscription?.autoTranslate is true and subscription.autoTranslateDisplay is true and subscription.autoTranslateLanguage and RocketChat.settings.get('AutoTranslate_Enabled') + if RocketChat.settings.get('AutoTranslate_Enabled') and this.u?._id isnt Meteor.userId() and !RocketChat.MessageTypes.isSystemMessage(this) + subscription = RocketChat.models.Subscriptions.findOne({ rid: this.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); + return subscription.autoTranslate && !!subscription?.autoTranslateDisplay isnt !!this.autoTranslateShowInverse edited: -> return Template.instance().wasEdited