From 8ddb0905263a2d0bce433207427273254a1dcec3 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Mon, 11 Sep 2017 16:02:30 -0500 Subject: [PATCH] i18n is now provided via the rocketlets and load them when a rocketlet is added --- packages/rocketchat-api/server/api.js | 9 +++++ .../.npm/package/npm-shrinkwrap.json | 10 +++--- .../client/lib/startup/commands.js | 26 ++++++++------ .../assets/stylesheets/rocketlets.css | 0 .../client/admin/rocketlets.html | 6 +++- .../client/admin/rocketlets.js | 21 ++++++++++- .../client/communication/websockets.js | 7 ++++ .../client/orchestrator.js | 23 ++++++++++++ packages/rocketchat-rocketlets/package.js | 7 ++-- .../server/bridges/activation.js | 35 +++++++++++++++++++ .../server/bridges/bridges.js | 7 ++++ .../server/bridges/index.js | 2 ++ .../server/bridges/settings.js | 23 ++++++++++-- .../server/communication/rest.js | 25 +++++++++++-- .../server/converters/settings.js | 4 +++ 15 files changed, 180 insertions(+), 25 deletions(-) create mode 100644 packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css create mode 100644 packages/rocketchat-rocketlets/server/bridges/activation.js diff --git a/packages/rocketchat-api/server/api.js b/packages/rocketchat-api/server/api.js index c7816e0afad..d53bd9b6e63 100644 --- a/packages/rocketchat-api/server/api.js +++ b/packages/rocketchat-api/server/api.js @@ -66,6 +66,15 @@ class API extends Restivus { }; } + notFound(msg) { + return { + statusCode: 404, + body: { + success: false, + error: msg ? msg : 'Resource not found' + } + }; + } unauthorized(msg) { return { diff --git a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json index 788d7c87977..00561635dcd 100644 --- a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json @@ -1085,13 +1085,13 @@ "from": "mime@>=1.2.11 <2.0.0" }, "mime-db": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "from": "mime-db@>=1.29.0 <1.30.0" + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "from": "mime-db@>=1.30.0 <1.31.0" }, "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "from": "mime-types@>=2.0.8 <3.0.0" }, "minimatch": { diff --git a/packages/rocketchat-lib/client/lib/startup/commands.js b/packages/rocketchat-lib/client/lib/startup/commands.js index 01d97477c1f..91456a9eed6 100644 --- a/packages/rocketchat-lib/client/lib/startup/commands.js +++ b/packages/rocketchat-lib/client/lib/startup/commands.js @@ -1,11 +1,17 @@ -Meteor.startup(function _loadDynamicallyDefinedCommands() { - // The reason there is a 500 millisecond delay is so that we are - // a little "easier" on the server during start up - setTimeout(() => { - RocketChat.API.v1.get('commands.list').then(function _loadedCommands(result) { - result.commands.forEach((command) => { - RocketChat.slashCommands.commands[command.command] = command; +//Track logins and when they login, get the commands +(() => { + let oldUserId = null; + + Meteor.autorun(() => { + const newUserId = Meteor.userId(); + if (oldUserId === null && newUserId) { + RocketChat.API.v1.get('commands.list').then(function _loadedCommands(result) { + result.commands.forEach((command) => { + RocketChat.slashCommands.commands[command.command] = command; + }); }); - }); - }, 500); -}); + } + + oldUserId = Meteor.userId(); + }); +})(); diff --git a/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css b/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 62c73ba09a9..74fbb58e9f4 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -9,7 +9,11 @@
{{#requiresPermission 'manage-rocketlets'}} -

Hello

+ {{#each rocketlets}} + + {{/each}} {{/requiresPermission}}
diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.js b/packages/rocketchat-rocketlets/client/admin/rocketlets.js index bf10e3895b2..a869c96ec1c 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.js +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.js @@ -1,3 +1,22 @@ Template.rocketlets.onCreated(function() { - console.log('hello'); + const instance = this; + this.ready = new ReactiveVar(false); + this.rocketlets = new ReactiveVar([]); + + RocketChat.API.get('rocketlets').then((result) => { + instance.rocketlets.set(result.rocketlets); + }); +}); + +Template.rocketlets.helpers({ + isReady() { + if (Template.instance().ready != null) { + return Template.instance().ready.get(); + } + + return false; + }, + rocketlets() { + return Template.instance().rocketlets.get(); + } }); diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js index 5288636a3d0..b7aef6dc1df 100644 --- a/packages/rocketchat-rocketlets/client/communication/websockets.js +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -3,12 +3,19 @@ export class RocketletWebsocketReceiver { this.orch = orch; this.streamer = new Meteor.Streamer('rocketlets'); + this.streamer.on('rocketlet/added', this.onRocketletAdded.bind(this)); this.streamer.on('command/added', this.onCommandAdded.bind(this)); this.streamer.on('command/disabled', this.onCommandDisabled.bind(this)); this.streamer.on('command/updated', this.onCommandUpdated.bind(this)); this.streamer.on('command/removed', this.onCommandDisabled.bind(this)); } + onRocketletAdded(rocketletId) { + RocketChat.API.get(`rocketlets/${ rocketletId }`).then((result) => { + this.orch.parseAndLoadLanguages(result.rocketlet.languages); + }); + } + onCommandAdded(command) { RocketChat.API.v1.get('commands.getOne', { command }).then((result) => { RocketChat.slashCommands.commands[command] = result.command; diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index 4bedcc9e56b..d2ff6dd0211 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -5,6 +5,7 @@ class RocketletClientOrchestrator { this.ws = new RocketletWebsocketReceiver(this); this._addAdminMenuOption(); + setTimeout(() => this._loadLanguages(), 500); } getWsListener() { @@ -20,6 +21,28 @@ class RocketletClientOrchestrator { } }); } + + _loadLanguages() { + if (!Meteor.user()) { + return; + } + + RocketChat.API.get('rocketlets?languagesOnly=true').then((info) => { + info.rocketlets.forEach((rlInfo) => this.parseAndLoadLanguages(rlInfo.languages)); + }); + } + + parseAndLoadLanguages(languages) { + Object.keys(languages).forEach((key) => { + try { + const json = JSON.parse(languages[key]); + + TAPi18next.addResourceBundle(key, 'project', json); + } catch (e) { + // Failed to parse the json + } + }); + } } Meteor.startup(function _rlClientOrch() { diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 0071297ed1a..5ea4ba27e3e 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -25,6 +25,7 @@ Package.onUse(function(api) { // Bridges api.addFiles([ + 'server/bridges/activation.js', 'server/bridges/bridges.js', 'server/bridges/commands.js', 'server/bridges/environmental.js', @@ -67,6 +68,8 @@ Package.onUse(function(api) { 'client/admin/rocketlets.js' ], 'client'); + api.addFiles('assets/stylesheets/rocketlets.css', 'client'); + // Client orchestrator api.addFiles('client/orchestrator.js', 'client'); @@ -76,6 +79,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.23', - 'temporary-rocketlets-ts-definition': '0.6.25' + 'temporary-rocketlets-server': '0.1.26', + 'temporary-rocketlets-ts-definition': '0.6.26' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/activation.js b/packages/rocketchat-rocketlets/server/bridges/activation.js new file mode 100644 index 00000000000..6833622fbec --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/activation.js @@ -0,0 +1,35 @@ +export class RocketletActivationBridge { + constructor(orch) { + this.orch = orch; + } + + rocketletEnabled(rocketlet) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been enabled.`); + } + + rocketletDisabled(rocketlet) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been disabled.`); + } + + rocketletLoaded(rocketlet, enabled) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been loaded and enabled? ${ enabled }`); + + if (enabled) { + this.orch.getNotifier().rocketletAdded(rocketlet.getID()); + } + } + + rocketletUpdated(rocketlet, enabled) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been updated and enabled? ${ enabled }`); + + if (enabled) { + this.orch.getNotifier().rocketletUpdated(rocketlet.getID()); + } + } + + rocketletRemoved(rocketlet) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been removed.`); + + this.orch.getNotifier().rocketletRemoved(rocketlet.getID()); + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/bridges.js b/packages/rocketchat-rocketlets/server/bridges/bridges.js index 07f5d182a9d..3afa40d44a9 100644 --- a/packages/rocketchat-rocketlets/server/bridges/bridges.js +++ b/packages/rocketchat-rocketlets/server/bridges/bridges.js @@ -1,4 +1,6 @@ import { RocketletBridges } from 'temporary-rocketlets-server/server/bridges'; + +import { RocketletActivationBridge } from './activation'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; import { RocketletHttpBridge } from './http'; @@ -12,6 +14,7 @@ export class RealRocketletBridges extends RocketletBridges { constructor(orch) { super(); + this._actBridge = new RocketletActivationBridge(orch); this._cmdBridge = new RocketletCommandsBridge(orch); this._envBridge = new RocketletEnvironmentalVariableBridge(orch); this._httpBridge = new RocketletHttpBridge(); @@ -42,6 +45,10 @@ export class RealRocketletBridges extends RocketletBridges { return this._persistBridge; } + getRocketletActivationBridge() { + return this._actBridge; + } + getRoomBridge() { return this._roomBridge; } diff --git a/packages/rocketchat-rocketlets/server/bridges/index.js b/packages/rocketchat-rocketlets/server/bridges/index.js index 6f6662360c7..f464cffcb32 100644 --- a/packages/rocketchat-rocketlets/server/bridges/index.js +++ b/packages/rocketchat-rocketlets/server/bridges/index.js @@ -1,4 +1,5 @@ import { RealRocketletBridges } from './bridges'; +import { RocketletActivationBridge } from './activation'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; import { RocketletHttpBridge } from './http'; @@ -10,6 +11,7 @@ import { RocketletUserBridge } from './users'; export { RealRocketletBridges, + RocketletActivationBridge, RocketletCommandsBridge, RocketletEnvironmentalVariableBridge, RocketletHttpBridge, diff --git a/packages/rocketchat-rocketlets/server/bridges/settings.js b/packages/rocketchat-rocketlets/server/bridges/settings.js index 25ea83df39f..0971e0cb9e2 100644 --- a/packages/rocketchat-rocketlets/server/bridges/settings.js +++ b/packages/rocketchat-rocketlets/server/bridges/settings.js @@ -2,12 +2,29 @@ export class RocketletSettingBridge { constructor(orch) { this.orch = orch; this.allowedGroups = []; - this.allowedSettings = []; + this.disallowedSettings = [ + 'Accounts_RegistrationForm_SecretURL', 'CROWD_APP_USERNAME', 'CROWD_APP_PASSWORD', 'Direct_Reply_Username', + 'Direct_Reply_Password', 'SMTP_Username', 'SMTP_Password', 'FileUpload_S3_AWSAccessKeyId', 'FileUpload_S3_AWSSecretAccessKey', + 'FileUpload_S3_BucketURL', 'FileUpload_GoogleStorage_Bucket', 'FileUpload_GoogleStorage_AccessId', + 'FileUpload_GoogleStorage_Secret', 'GoogleVision_ServiceAccount', 'Allow_Invalid_SelfSigned_Certs', 'GoogleTagManager_id', + 'Bugsnag_api_key', 'LDAP_CA_Cert', 'LDAP_Reject_Unauthorized', 'LDAP_Domain_Search_User', 'LDAP_Domain_Search_Password', + 'Livechat_secret_token', 'Livechat_Knowledge_Apiai_Key', 'AutoTranslate_GoogleAPIKey', 'MapView_GMapsAPIKey', + 'Meta_fb_app_id', 'Meta_google-site-verification', 'Meta_msvalidate01', 'Accounts_OAuth_Dolphin_secret', + 'Accounts_OAuth_Drupal_secret', 'Accounts_OAuth_Facebook_secret', 'Accounts_OAuth_Github_secret', 'API_GitHub_Enterprise_URL', + 'Accounts_OAuth_GitHub_Enterprise_secret', 'API_Gitlab_URL', 'Accounts_OAuth_Gitlab_secret', 'Accounts_OAuth_Google_secret', + 'Accounts_OAuth_Linkedin_secret', 'Accounts_OAuth_Meteor_secret', 'Accounts_OAuth_Twitter_secret', 'API_Wordpress_URL', + 'Accounts_OAuth_Wordpress_secret', 'Push_apn_passphrase', 'Push_apn_key', 'Push_apn_cert', 'Push_apn_dev_passphrase', + 'Push_apn_dev_key', 'Push_apn_dev_cert', 'Push_gcm_api_key', 'Push_gcm_project_number', 'SAML_Custom_Default_cert', + 'SAML_Custom_Default_private_key', 'SlackBridge_APIToken', 'Smarsh_Email', 'SMS_Twilio_Account_SID', 'SMS_Twilio_authToken' + ]; } getAll(rocketletId) { console.log(`The Rocketlet ${ rocketletId } is getting all the settings.`); - throw new Error('Method not implemented.'); + + return RocketChat.models.Settings.find({ _id: { $nin: this.disallowedSettings } }).fetch().map((s) => { + this.orch.getConverters().get('settings').convertToRocketlet(s); + }); } getOneById(id, rocketletId) { @@ -38,7 +55,7 @@ export class RocketletSettingBridge { isReadableById(id, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is checking if they can read the setting ${ id }.`); - return this.allowedSettings.includes(id); + return !this.disallowedSettings.includes(id); } updateOne(setting, rocketletId) { diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index 0b6bc515379..50aff66c52b 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -40,7 +40,19 @@ export class RocketletsRestApi { this.api.addRoute('', { authRequired: true }, { get() { - const rocketlets = manager.get().map(prl => prl.getInfo()); + const rocketlets = manager.get().map(prl => { + if (this.queryParams.languagesOnly) { + return { + id: prl.getID(), + languages: prl.getStorageItem().languageFiles + }; + } else { + const info = prl.getInfo(); + info.languages = prl.getStorageItem().languageFiles; + + return info; + } + }); return { success: true, rocketlets }; }, @@ -60,9 +72,16 @@ export class RocketletsRestApi { this.api.addRoute(':id', { authRequired: true }, { get() { console.log('Getting:', this.urlParams.id); - const rocketlet = manager.getOneById(this.urlParams.id).getInfo(); + const prl = manager.getOneById(this.urlParams.id); - return { success: true, rocketlet }; + if (prl) { + const info = prl.getInfo(); + info.languages = prl.getStorageItem().languageFiles; + + return { success: true, rocketlet: info }; + } else { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } }, post() { console.log('Updating:', this.urlParams.id); diff --git a/packages/rocketchat-rocketlets/server/converters/settings.js b/packages/rocketchat-rocketlets/server/converters/settings.js index edce911c6cf..f6a6d3dabdd 100644 --- a/packages/rocketchat-rocketlets/server/converters/settings.js +++ b/packages/rocketchat-rocketlets/server/converters/settings.js @@ -8,6 +8,10 @@ export class RocketletSettingsConverter { convertById(settingId) { const setting = RocketChat.models.Settings.findOneById(settingId); + return this.convertToRocketlet(setting); + } + + convertToRocketlet(setting) { return { id: setting._id, type: this._convertTypeToRocketlet(setting.type),