diff --git a/.meteor/packages b/.meteor/packages index c4f5cd8c17..02cf6ebfb9 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -36,7 +36,6 @@ benmgreene:moment-range email@1.1.17 zimme:active-route cfs:filesystem -mrt:flash-messages raix:ui-dropped-event brylie:accounts-admin-ui brylie:first-user-admin diff --git a/.meteor/versions b/.meteor/versions index 105ae4e1ac..7ed00312a9 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -101,7 +101,6 @@ mongo@1.1.12 mongo-id@1.0.5 mongo-livedata@1.0.12 mpowaga:string-template@0.1.0 -mrt:flash-messages@1.0.1 npm-bcrypt@0.9.1 npm-mongo@1.5.48 oauth@1.1.11 diff --git a/api_keys/client/api_key.js b/api_keys/client/api_key.js index f6c282a1f5..f20745fba8 100644 --- a/api_keys/client/api_key.js +++ b/api_keys/client/api_key.js @@ -37,7 +37,11 @@ Template.apiKey.events({ if (error) { sAlert.error(error); } else { - sAlert.success(TAPi18n.__('apiKeys_getApiKeyButton_success')); + // Get success message translation + const message = TAPi18n.__('apiKeys_getApiKeyButton_success'); + + // Alert the user of success + sAlert.success(message); } }); }, diff --git a/apis/client/delete/delete.js b/apis/client/delete/delete.js index 6b8909699f..ae4752452c 100644 --- a/apis/client/delete/delete.js +++ b/apis/client/delete/delete.js @@ -13,8 +13,11 @@ Template.deleteApiBackendConfirmation.events({ // Route to catalogue Router.go('catalogue'); + // Get success message translation + const message = TAPi18n.__('deleteApiBackendConfirmation_successMessage'); + // Alert the user of success - sAlert.success(instance.data.name + ' was successfully deleted!'); + sAlert.success(message + instance.data.name); // Dismiss the confirmation modal Modal.hide(); diff --git a/apis/client/edit/autoform.js b/apis/client/edit/autoform.js deleted file mode 100644 index 3497e6f4b6..0000000000 --- a/apis/client/edit/autoform.js +++ /dev/null @@ -1,160 +0,0 @@ -import { Apis } from '/apis/collection'; - -AutoForm.hooks({ - editApiForm: { - beginSubmit: function () { - // Disable form elements while submitting form - $('[data-schema-key], button').attr("disabled", "disabled"); - // Change button text - $('#add-apibackends').text('Submitting...'); - }, - endSubmit: function () { - // Enable form elements after form submission - $('[data-schema-key], button').removeAttr("disabled"); - // Change button text to original - $('#add-apibackends').text('Submit'); - }, - before: { - insert: function (apiBackendForm) { - // Keep the context to use inside the callback function - var context = this; - - // Send the API Backend to API Umbrella - Meteor.call('createApiBackendOnApiUmbrella', apiBackendForm, function(error, apiUmbrellaWebResponse) { - - if (apiUmbrellaWebResponse.http_status === 200) { - // Get the API Backend ID from API Umbrella - var apiUmbrellaApiId = apiUmbrellaWebResponse.result.data.api.id; - - // Append the API Umbrella ID to the local API Backend - apiBackendForm.id = apiUmbrellaApiId; - - context.result(apiBackendForm); - } else { - var errors = _.values(apiUmbrellaWebResponse.errors); - - // Flatten all error descriptions to show using sAlert - errors = _.flatten(errors); - _.each(errors, function(error) { - // Display error to the user, keep the sAlert box visible. - sAlert.error(error, {timeout: 'none'}); - // TODO: Figure out a way to send the errors back to the autoform fields, as if it were client validation, - // and get rid of sAlert here. - }); - - // Cancel form submission on error, so user see the sAlert.error message and edit the incorrect fields - context.result(false); - } - }); - }, - update: function (apiBackendForm) { - // Keep the context to use inside the callback function - var context = this; - - // Get current API Backend document for modification - var apiBackend = context.currentDoc; - - // Get the set of updated properties - var setApiBackendProperties = context.updateDoc.$set; - - // Get the set of properties to remove - var unsetApiBackendProperties = context.updateDoc.$unset; - - // Update properties on API Backend document - for (let property in setApiBackendProperties) { - apiBackend[property] = setApiBackendProperties[property]; - } - - // Delete unused properties from API Backend object - for (let property in unsetApiBackendProperties) { - delete apiBackend[property]; - } - - // Get ID of API Umbrella backend (not the Apinf document ID) - var apiUmbrellaBackendId = apiBackend.id; - - // Send the API Backend to API Umbrella - response = Meteor.call( - 'updateApiBackendOnApiUmbrella', - apiUmbrellaBackendId, - apiBackend, - function(error, apiUmbrellaWebResponse) { - // Check for API Umbrella error - if (apiUmbrellaWebResponse.http_status === 204) { - // If status is OK, submit form - context.result(apiBackendForm); - } else { - // If there are errors - var errors = _.values(apiUmbrellaWebResponse.errors); - - // Flatten all error descriptions to show using sAlert - errors = _.flatten(errors); - _.each(errors, function(error) { - //Display error to the user, keep the sAlert box visible. - sAlert.error(error, {timeout: 'none'}); - // TODO: Figure out a way to send the errors back to the autoform fields, as if it were client validation, - // and get rid of sAlert here. - }); - - // Cancel form submission on error, - // so user see the error message and edit the incorrect fields - context.result(false); - } - }); - } - }, - onSuccess: function () { - // Get current API Backend ID - var apiBackendId = this.docId; - - // Attach API Backend ID to API Doc, if possible - if (Session.get('apiDocsId')) { - // Get the API Documentation ID, if available - var apiDocsId = Session.get('apiDocsId'); - - // Add the API Backend ID to the API Documentation document - ApiDocs.update( - apiDocsId, - { - $set: { - apiBackendId: apiBackendId - } - } - ); - - // Reset the apiDocsID Session variable - Session.set('apiDocsId', undefined); - } - - - // Redirect to the just created API Backend page - Router.go('viewApiBackend', {_id: apiBackendId}); - - // Get the API Backend object - var apiBackend = Apis.findOne(apiBackendId); - - // Get API Umbrella backend ID from API Backend - var apiUmbrellaApiId = apiBackend.id; - - // Publish the API Backend on API Umbrella - Meteor.call('publishApiBackendOnApiUmbrella', apiUmbrellaApiId, function(error, apiUmbrellaWebResponse) { - - // Check for a successful response - if (apiUmbrellaWebResponse.http_status === 201) { - // Alert the user of the success - sAlert.success("API Backend successfully published."); - } else { - // If there are errors, inform the user - var errors = _.values(apiUmbrellaWebResponse.errors); - - // Flatten all error descriptions to show using sAlert - errors = _.flatten(errors); - _.each(errors, function(error) { - // Display error to the user, keep the sAlert box visible. - sAlert.error(error, {timeout: 'none'}); - }); - } - }); - } - } -}); diff --git a/apis/client/edit/edit.html b/apis/client/edit/edit.html deleted file mode 100644 index aef391e59e..0000000000 --- a/apis/client/edit/edit.html +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/apis/client/edit/edit.js b/apis/client/edit/edit.js deleted file mode 100644 index 7052dce98d..0000000000 --- a/apis/client/edit/edit.js +++ /dev/null @@ -1,35 +0,0 @@ -import { Apis } from '/apis/collection'; - -Template.editApi.created = function () { - // Get reference to current Router - var router = Router.current(); - - // Get the API Backend ID from Router - var apiBackendId = router.params._id; - - if (apiBackendId) { - // Subscription to apiBackends collection - this.subscribe('apiBackend', apiBackendId); - } -}; - -Template.editApi.helpers({ - 'apiBackend': function () { - // Get the current Router - var router = Router.current(); - - // Check router for _id parameter - if (router.params._id) { - // Get the API Backend ID - var apiBackendId = router.params._id; - - // Get the API Backend - var apiBackend = Apis.findOne(apiBackendId); - - return apiBackend; - } - }, - 'apisCollection': function () { - return Apis; - } -}); diff --git a/apis/client/edit/form_hints/form_hints.js b/apis/client/edit/form_hints/form_hints.js deleted file mode 100644 index 2228446a5d..0000000000 --- a/apis/client/edit/form_hints/form_hints.js +++ /dev/null @@ -1,87 +0,0 @@ -var helpData = { - 'api_name': { - message: TAPi18n.__('editApi_hints_api_name'), - options: { - placement: 'left' - } - }, - 'backend_protocol': { - message: TAPi18n.__('editApi_hints_backend_protocol'), - options: { - placement: 'left' - } - }, - 'backend_port': { - message: TAPi18n.__('editApi_hints_backend_port'), - options: { - placement: 'left' - } - }, - 'servers': { - message: TAPi18n.__('editApi_hints_servers'), - options: { - placement: 'left' - } - }, - 'backend_host': { - message: TAPi18n.__('editApi_hints_backend_host'), - options: { - placement: 'left' - } - }, - 'frontend_host': { - message: TAPi18n.__('editApi_hints_frontend_host'), - options: { - placement: 'left' - } - }, - 'url_matches': { - message: TAPi18n.__('editApi_hints_url_matches'), - options: { - placement: 'left' - } - }, - 'append_query_string': { - message: TAPi18n.__('editApi_hints_append_query_string'), - options: { - placement: 'left' - } - }, - 'set_headers': { - message: TAPi18n.__('editApi_hints_set_headers'), - options: { - placement: 'left' - } - }, - 'http_basic_auth': { - message: TAPi18n.__('editApi_hints_http_basic_auth'), - options: { - placement: 'left' - } - }, - 'require_https': { - message: TAPi18n.__('editApi_hints_require_https'), - options: { - placement: 'left' - } - }, - 'api_key_verification_level': { - message: TAPi18n.__('editApi_hints_api_key_verification_level'), - options: { - placement: 'left' - } - }, - 'balance_algorithm': { - message: TAPi18n.__('editApi_hints_api_balance_algorithm'), - options: { - placement: 'left' - } - }, - 'settings': { - message: TAPi18n.__('editApi_hints_settings'), - options: { - placement: 'left' - } - } -}; -InlineHelp.initHelp(helpData); diff --git a/apis/client/edit/form_hints/form_hints.less b/apis/client/edit/form_hints/form_hints.less deleted file mode 100644 index 2fda8ef849..0000000000 --- a/apis/client/edit/form_hints/form_hints.less +++ /dev/null @@ -1,5 +0,0 @@ -.show-help { - float: right; - padding-right: 0.4em; - padding-top: 0.4em; -} diff --git a/apis/client/import/import.html b/apis/client/import/import.html index 3b4cc5e306..61ee1053b0 100644 --- a/apis/client/import/import.html +++ b/apis/client/import/import.html @@ -24,5 +24,4 @@
- {{> flashMessages}} diff --git a/apis/client/import/import.js b/apis/client/import/import.js index a126d0da2a..5e81ee1b68 100644 --- a/apis/client/import/import.js +++ b/apis/client/import/import.js @@ -1,174 +1,150 @@ Template.importApiConfiguration.rendered = function () { - // keep current template instance - var instance = this; + const instance = this; // initialises ace editor - instance.editor = ace.edit("editor"); + instance.editor = ace.edit('editor'); // theme for editor - instance.editor.setTheme("ace/theme/idle_fingers"); + instance.editor.setTheme('ace/theme/idle_fingers'); // code highlights for editor (JSON) - instance.editor.getSession().setMode("ace/mode/json"); + instance.editor.getSession().setMode('ace/mode/json'); // custom message (tutorial) in json format - var tips = { - "How_to_import_configurations": { - "option_1" : "Upload existing config file.", - "option_2" : "Paste configurations here.", - "available_file_extensions:" : "JSON, YAML or TXT." - } + const tips = { + 'How_to_import_configurations': { + 'option_1': 'Upload existing config file.', + 'option_2': 'Paste configurations here.', + 'available_file_extensions:': 'JSON, YAML or TXT.', + }, }; // parses json object to string with indentation (parsing to string needed for ace editor) - var jsonString = JSON.stringify(tips, null, '\t'); + const jsonString = JSON.stringify(tips, null, '\t'); // pastes initial value to editor instance.editor.setValue(jsonString); - }; // Get reference to template instance Template.importApiConfiguration.created = function () { - - var instance = this; + const instance = this; // function attached to template instance checks file extension instance.endsWith = function (filename, suffixList) { - // variable that keeps state of is this filename contains provided extensions - false by default - var state = false; + let state = false; // iterating through extensions passed into suffixList array - for (var i=0; i - {{> flashMessages}} diff --git a/apis/client/import_documentation/import.js b/apis/client/import_documentation/import.js index e5ee2d41da..f363732e18 100644 --- a/apis/client/import_documentation/import.js +++ b/apis/client/import_documentation/import.js @@ -1,76 +1,72 @@ Template.importApiDocumentation.events({ 'change #apiDocumentationFile': function (event, template) { - //console.log(AutoForm.reactiveFormData()); + // console.log(AutoForm.reactiveFormData()); // Allowed file extensions for API documentation file - var acceptedExtensions = ["yaml", "yml", "json"]; + const acceptedExtensions = ['yaml', 'yml', 'json']; // Current template instance - var instance = Template.instance(); + const instance = Template.instance(); // Iterates through each file uploaded - FS.Utility.eachFile(event, function(file) { - + FS.Utility.eachFile(event, function (file) { if (file) { - // Get file's name & parse the file string to URI object - var fileName = new URI(file.name); + const fileName = new URI(file.name); // Get the file extension - var fileExtension = fileName.suffix().toLowerCase(); + const fileExtension = fileName.suffix().toLowerCase(); // Check if the file suffix is in the allowed extensions list - var extensionAllowed = _.contains(acceptedExtensions, fileExtension); + const extensionAllowed = _.contains(acceptedExtensions, fileExtension); // Read file if the extension is allowed if (extensionAllowed) { - // Initialises new reader instance - var reader = new FileReader(); + const reader = new FileReader(); // Reads file - reader.readAsText(file, "UTF-8"); + reader.readAsText(file, 'UTF-8'); reader.onload = function (event) { - // Gets file contents - var importedFile = event.target.result; + const importedFile = event.target.result; // Checks for correct JSON or YAML syntax in file contents if (JSON.parse(importedFile) || jsyaml.safeLoad(importedFile)) { - - var doc = {}; + let doc = {}; // Checks file's extension for its conversion to JSON object if (fileExtension === 'json') { - // Convert JSON string to JSON object doc = JSON.parse(importedFile); } else if (_.contains(['yaml', 'yml'], fileExtension)) { - // Convert YAML string/object to JSON object doc = jsyaml.load(importedFile); } // Insert fine contents to a colletion - var apiDocsId = ApiDocs.insert(doc); + const apiDocsId = ApiDocs.insert(doc); // Set session variable containing API Docs ID, // used for attaching apiBackendId to apiDocs document on success Session.set('apiDocsId', apiDocsId); } else { + // Get error message text + const message = TAPi18n.__('importApiDocumentation_fileReadError_message'); // Notifies user if not able to parse the file either as JSON or YAML objects. - FlashMessages.sendError("Error when reading the file. Please check file contents for errors."); - + sAlert.error(message); } - } + }; } else { + // Get error message text + const message = TAPi18n.__('importApiDocumentation_fileExtensionError_message'); // Notifies user if file extension provided is not supported - FlashMessages.sendError("Only .json and .yaml(.yml) files are supported."); + sAlert.error(message); } } }); - } + }, }); diff --git a/apis/client/lib/router.js b/apis/client/lib/router.js index dc4acaaf97..3b27dbec0b 100644 --- a/apis/client/lib/router.js +++ b/apis/client/lib/router.js @@ -1,31 +1,18 @@ -Router.route("/api/new", function () { - this.render("addApi"); - this.layout("masterLayout"); +Router.route('/api/new', function () { + this.render('addApi'); + this.layout('masterLayout'); }, { - name: "addApi" + name: 'addApi', }); -Router.route("/api/:_id/", function () { - // Save a reference to route, for use inside method callback function - const route = this; - - // Get current API Backend ID - const apiBackendId = Router.current().params._id; - - // Ensure current user is authorized to view backend - Meteor.call("currentUserCanViewApi", apiBackendId, function (error, userIsAuthorized) { - if (userIsAuthorized) { - route.render("viewApiBackend"); - route.layout("masterLayout"); - } else { - Router.go("notAuthorized"); - } - }); -},{ - name: "viewApi", +Router.route('/api/import', function () { + this.render('importApiConfiguration'); + this.layout('masterLayout'); +}, { + name: 'importApiConfiguration', }); -Router.route("/api/:_id/edit", function () { +Router.route('/api/:_id/', function () { // Save a reference to route, for use inside method callback function const route = this; @@ -33,27 +20,14 @@ Router.route("/api/:_id/edit", function () { const apiBackendId = Router.current().params._id; // Ensure current user is authorized to view backend - Meteor.call("currentUserCanEditApi", apiBackendId, function (error, userIsAuthorized) { + Meteor.call('currentUserCanViewApi', apiBackendId, function (error, userIsAuthorized) { if (userIsAuthorized) { - route.render("viewApiBackend"); - route.layout("masterLayout"); + route.render('viewApiBackend'); + route.layout('masterLayout'); } else { - Router.go("notAuthorized"); + Router.go('notAuthorized'); } }); }, { - name: "editApi" -}); - -Router.map(function() { - this.route("manageApiBackends", { - path: "/manage", - layoutTemplate: "masterLayout" - }); - - this.route("importApiConfiguration", { - path: "import/api", - layoutTemplate: "masterLayout", - render: "importApiConfiguration" - }); + name: 'viewApi', }); diff --git a/apis/client/manage/manage.html b/apis/client/manage/manage.html deleted file mode 100644 index 5fd1e733d6..0000000000 --- a/apis/client/manage/manage.html +++ /dev/null @@ -1,86 +0,0 @@ - diff --git a/apis/client/manage/manage.js b/apis/client/manage/manage.js deleted file mode 100644 index 9d3bd70fe8..0000000000 --- a/apis/client/manage/manage.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Apis } from '/apis/collection'; - -Template.manageApiBackends.created = function () { - this.subscribe('myManagedApis'); -}; - -Template.manageApiBackends.rendered = function () { - const myManagedApis = Apis.find().fetch(); - - // console.log(myManagedApis); -}; - -Template.manageApiBackends.helpers({ - 'managedApis': function () { - // Get the current user - const userId = Meteor.user()._id; - - // Get API Backends managed by user (provided by subscription) - const managedApis = Apis.find({ managerIds: userId }); - - return managedApis; - }, -}); - -Template.manageApiBackends.events({ - 'click #deleteModal': function () { - // Get API backend ID from template data - const api = this; - - // Show Delete API Backend confirmation modal, for current API backend - Modal.show('deleteApiBackendConfirmation', api); - }, -}); diff --git a/apis/client/manage/manage.less b/apis/client/manage/manage.less deleted file mode 100644 index 3aebd24587..0000000000 --- a/apis/client/manage/manage.less +++ /dev/null @@ -1,5 +0,0 @@ -.managed-apis { - .api-panel-title { - cursor: pointer; - } -} diff --git a/apis/client/view/header/header.html b/apis/client/view/header/header.html index 4d264fcd70..2642453324 100644 --- a/apis/client/view/header/header.html +++ b/apis/client/view/header/header.html @@ -25,7 +25,7 @@

class="api-card-bookmark" data-toggle="tooltip" data-placement="bottom" - title="{{_ 'catalogue-Bookmark-Tooltip_NonUser'}}"> + title="{{_ 'catalogue_bookmarkTooltip_nonUser'}}"> {{ api.bookmarkCount }} diff --git a/apis/client/view/settings/settings.html b/apis/client/view/settings/settings.html index 30728c13fb..2238f057fe 100644 --- a/apis/client/view/settings/settings.html +++ b/apis/client/view/settings/settings.html @@ -6,7 +6,9 @@

-

{{_ "editApiBackendForm-uploadLogo" }}

+

+ {{_ "viewApiBackendSettings_uploadLogo_heading" }} +

{{_ "viewApiBackendSettings_uploadLogoText" }}

diff --git a/apis/flags/client/autoform.js b/apis/flags/client/autoform.js index b0bea57597..72d7ee8a5c 100644 --- a/apis/flags/client/autoform.js +++ b/apis/flags/client/autoform.js @@ -1,24 +1,25 @@ AutoForm.addHooks('insertApiFlag', { onSuccess (formType, result) { - // Hide modal Modal.hide('flagApiModal'); // Checks formtype if (formType === 'insert') { + // Get insert message translation + const message = TAPi18n.__('flagApiModal_removeApiFlag_insertMessage'); // Show message to a user - sAlert.success(TAPi18n.__('flagApiModal_removeApiFlag_insertMessage')); - + sAlert.success(message); } else if (formType === 'update') { + // Get update message translation + const message = TAPi18n.__('flagApiModal_removeApiFlag_updateMessage'); // Show message to a user - sAlert.success(TAPi18n.__('flagApiModal_removeApiFlag_updateMessage')); + sAlert.success(message); } }, onError (formType, error) { - // Throw an error if one has been chatched return new Meteor.Error(error); - } + }, }); diff --git a/apis/flags/client/flag.js b/apis/flags/client/flag.js index e7f1e2d994..9fd50ec6d9 100644 --- a/apis/flags/client/flag.js +++ b/apis/flags/client/flag.js @@ -1,5 +1,4 @@ Template.flagApiModal.onCreated(function () { - // Create reference to instance const instance = this; @@ -9,7 +8,6 @@ Template.flagApiModal.onCreated(function () { Template.flagApiModal.helpers({ formType () { - // Create reference to instance const instance = Template.instance(); @@ -17,25 +15,22 @@ Template.flagApiModal.helpers({ return (instance.apiFlag) ? 'update' : 'insert'; }, apiFlag () { - // Create reference to instance const instance = Template.instance(); return instance.apiFlag; }, apiIsFlagged () { - // Create reference to instance const instance = Template.instance(); // Check if api exists and return boolean return (instance.apiFlag) ? true : false; - } + }, }); Template.flagApiModal.events({ 'click #remove-apiFlag': function () { - // Create reference to instance const instance = Template.instance(); @@ -44,12 +39,14 @@ Template.flagApiModal.events({ // Check if document has been removed if (removeApiFlag > 0) { + // Get success message translation + const message = TAPi18n.__('flagApiModal_removeApiFlag_successMessage'); // Show message to a user - sAlert.success(TAPi18n.__('flagApiModal_removeApiFlag_successMessage')); + sAlert.success(message); // Hide modal Modal.hide('flagApiModal'); } - } + }, }); diff --git a/apis/logo/upload/client/resumable.js b/apis/logo/upload/client/resumable.js index 39e6bbce74..de319a0d6b 100644 --- a/apis/logo/upload/client/resumable.js +++ b/apis/logo/upload/client/resumable.js @@ -1,6 +1,6 @@ import { ApiLogo } from '/apis/logo/collection/collection'; import { Apis } from '/apis/collection'; -import { fileNameEndsWith } from '/lib/helperFunctions/fileNameEndsWith'; +import { fileNameEndsWith } from '/core/helper_functions/file_name_ends_with'; Meteor.startup(function () { ApiLogo.resumable.on('fileAdded', function (file) { @@ -26,11 +26,18 @@ Meteor.startup(function () { // Update logo id field Apis.update(api._id, { $set: { apiLogoFileId } }); - sAlert.success(TAPi18n.__('apiLogo_resumable_successfully_uploaded')); + // Get success message translation + const message = TAPi18n.__('apiLogo_resumable_successfully_uploaded'); + + sAlert.success(message); return ApiLogo.resumable.upload(); } else { - sAlert.error(TAPi18n.__('apiLogo_resumable_acceptedExtensions')); + // Get error message translation related to accepted extensions + const message = TAPi18n.__('apiLogo_resumable_acceptedExtensions'); + + // Alert user of error + sAlert.error(message); } }); }); diff --git a/apis/logo/upload/client/upload.js b/apis/logo/upload/client/upload.js index 094d55f8a6..8cb163cebc 100644 --- a/apis/logo/upload/client/upload.js +++ b/apis/logo/upload/client/upload.js @@ -28,7 +28,10 @@ Template.uploadApiLogo.events({ // Remove API logo file id field Apis.update(instance.data.api._id, { $unset: { apiLogoFileId: '' } }); - sAlert.success(TAPi18n.__('uploadApiLogo_successfully_deleted')); + // Get deletion success message + const message = TAPi18n.__('uploadApiLogo_successfully_deleted'); + + sAlert.success(message); } }, }); diff --git a/both/collections/helpers/users.js b/both/collections/helpers/users.js deleted file mode 100644 index 8acd78cd90..0000000000 --- a/both/collections/helpers/users.js +++ /dev/null @@ -1,6 +0,0 @@ -Meteor.users.helpers({ - 'apiUmbrellaUsers': function () { - // Return all ApiUmbrellaUsers associated with this user ID - return ApiUmbrellaUsers.find({userId: this._id}); - } -}); diff --git a/both/collections/roles.js b/both/collections/roles.js deleted file mode 100644 index dbab186f7f..0000000000 --- a/both/collections/roles.js +++ /dev/null @@ -1,7 +0,0 @@ -Schemas.RolesSchema = new SimpleSchema({ - name: { - type: String - } -}); - -Meteor.roles.attachSchema(Schemas.RolesSchema); diff --git a/both/collections/users.js b/both/collections/users.js deleted file mode 100644 index 52700a50b1..0000000000 --- a/both/collections/users.js +++ /dev/null @@ -1,74 +0,0 @@ -Schemas.UserProfile = new SimpleSchema({ - name: { - type: String, - optional: true - }, - company: { - type: String, - optional: true - } -}); -// Username must be 3-15 alphanumeric string with hyphens allowed. -Schemas.RegEx.Username = /^[a-z0-9A-Z_\-]{3,15}$/; - -Schemas.User = new SimpleSchema({ - username: { - type: String, - regEx: Schemas.RegEx.Username, - optional: true - }, - apiUmbrellaUserId: { - type: String, - optional: true - }, - emails: { - type: [Object], - optional: false - }, - "emails.$.address": { - type: String, - regEx: SimpleSchema.RegEx.Email - }, - "emails.$.verified": { - type: Boolean - }, - createdAt: { - type: Date - }, - profile: { - type: Schemas.UserProfile - }, - services: { - type: Object, - optional: true, - blackbox: true - }, - roles: { - type: [String], - blackbox: true, - optional: true - } -}); - -// Fetch username invalid message -var usernameInvalid = TAPi18n.__("profile-usernameInvalid"); - -// Define custom validation error messages -Schemas.User.messages({ - "regEx username": [ - {exp: Schemas.RegEx.Username, msg: usernameInvalid} - ] -}); - -Meteor.users.attachSchema(Schemas.User); - -Meteor.users.allow({ - update: function(userId, user) { - // Only allow user to update own username - if (userId === user._id) { - return true; - } else { - return false; - } - } -}); diff --git a/branding/logo/upload/client/resumable.js b/branding/logo/upload/client/resumable.js index 3dffc6c277..bf95e3140e 100644 --- a/branding/logo/upload/client/resumable.js +++ b/branding/logo/upload/client/resumable.js @@ -1,23 +1,22 @@ import { Branding } from '/branding/collection'; import { ProjectLogo } from '/branding/logo/collection'; -import { fileNameEndsWith } from '/lib/helperFunctions/fileNameEndsWith'; +import { fileNameEndsWith } from '/core/helper_functions/file_name_ends_with'; -Meteor.startup( function() { - ProjectLogo.resumable.on('fileAdded', function(file) { +Meteor.startup(function () { + ProjectLogo.resumable.on('fileAdded', function (file) { return ProjectLogo.insert({ _id: file.uniqueIdentifier, filename: file.fileName, - contentType: file.file.type - }, function(err, projectLogoFile) { + contentType: file.file.type, + }, function (err, projectLogoFile) { if (err) { - console.warn("File creation failed!", err); + console.warn('File creation failed!', err); return; } - const acceptedExtensions = ["jpg", "jpeg", "png", "gif"]; + const acceptedExtensions = ['jpg', 'jpeg', 'png', 'gif']; if (fileNameEndsWith(file.file.name, acceptedExtensions)) { - // Get the id from project logo file object const projectLogoFileId = file.uniqueIdentifier; @@ -25,16 +24,22 @@ Meteor.startup( function() { const branding = Branding.findOne(); // Update logo id field - Branding.update(branding._id, {$set: { projectLogoFileId }}); + Branding.update(branding._id, { $set: { projectLogoFileId } }); + + // Get upload success message translation + const message = TAPi18n.__('uploadProjectLogo_successfully_uploaded'); - sAlert.success(TAPi18n.__('uploadProjectLogo_successfully_uploaded')); + // Alert user of successful upload + sAlert.success(message); return ProjectLogo.resumable.upload(); } else { + // Get extension error message + const message = TAPi18n.__('uploadProjectLogo_acceptedExtensions'); - sAlert.error(TAPi18n.__('uploadProjectLogo_acceptedExtensions')); + // Alert user of extension error + sAlert.error(message); } - }); }); }); diff --git a/branding/logo/upload/client/upload.js b/branding/logo/upload/client/upload.js index bb9e50821f..1938f762a1 100644 --- a/branding/logo/upload/client/upload.js +++ b/branding/logo/upload/client/upload.js @@ -1,7 +1,7 @@ import { Branding } from '/branding/collection'; import { ProjectLogo } from '/branding/logo/collection'; -Template.uploadProjectLogo.onCreated(function() { +Template.uploadProjectLogo.onCreated(function () { const instance = this; // Subscribe to Project logo @@ -10,14 +10,12 @@ Template.uploadProjectLogo.onCreated(function() { }); Template.uploadProjectLogo.events({ - 'click .delete-projectLogo': function(event, instance) { - + 'click .delete-projectLogo': function (event, instance) { // Show confirmation dialog to user const confirmation = confirm(TAPi18n.__('uploadProjectLogo_confirm_delete')); // Check if user clicked "OK" if (confirmation === true) { - // Get branding const branding = Branding.findOne(); @@ -31,16 +29,19 @@ Template.uploadProjectLogo.events({ ProjectLogo.remove(objectId); // Remove prokect logo file id field - Branding.update(branding._id, {$unset: { projectLogoFileId: "" }}); + Branding.update(branding._id, { $unset: { projectLogoFileId: '' } }); - sAlert.success(TAPi18n.__('uploadProjectLogo_successfully_deleted')); + // Get deletion success message translation + const message = TAPi18n.__('uploadProjectLogo_successfully_deleted'); + + // Alert user of successful delete + sAlert.success(message); } - } + }, }); Template.uploadProjectLogo.helpers({ - uploadedLogoLink: function() { - + uploadedLogoLink () { const currentProjectLogoFileId = this.branding.projectLogoFileId; // Convert to Mongo ObjectID @@ -52,11 +53,10 @@ Template.uploadProjectLogo.helpers({ // Check if project logo file is available if (currentProjectLogoFile) { // Get project logo file URL - return Meteor.absoluteUrl().slice(0, -1) + ProjectLogo.baseURL + "/id/" + currentProjectLogoFileId; + return Meteor.absoluteUrl().slice(0, -1) + ProjectLogo.baseURL + '/id/' + currentProjectLogoFileId; } }, - uploadedProjectLogoFile: function() { - + uploadedProjectLogoFile () { const currentProjectLogoFileId = this.branding.projectLogoFileId; // Convert to Mongo ObjectID @@ -69,5 +69,5 @@ Template.uploadProjectLogo.helpers({ if (currentProjectLogoFile) { return currentProjectLogoFile; } - } + }, }); diff --git a/catalogue/client/grid/grid.html b/catalogue/client/grid/grid.html index bed1f184a1..7af7b4c762 100644 --- a/catalogue/client/grid/grid.html +++ b/catalogue/client/grid/grid.html @@ -14,7 +14,7 @@ {{ api.name }} - {{_ "catalogueGrid-addedBy"}} + {{_ "catalogueGrid_addedBy"}} {{ api.getApiManagersByName }}

@@ -28,7 +28,7 @@ class="api-card-bookmark" data-toggle="tooltip" data-placement="bottom" - title="{{_ 'catalogue-Bookmark-Tooltip_User'}}"> + title="{{_ 'catalogue_BookmarkTooltip_user'}}"> {{> favourite api=api catalogueView=true }}

@@ -38,7 +38,7 @@ class="api-card-bookmark" data-toggle="tooltip" data-placement="bottom" - title="{{_ 'catalogue-Bookmark-Tooltip_NonUser'}}"> + title="{{_ 'catalogue_bookmarkTooltip_nonUser'}}"> {{ api.bookmarkCount }} diff --git a/catalogue/client/table/table.html b/catalogue/client/table/table.html index 287a64f965..4c399b59df 100644 --- a/catalogue/client/table/table.html +++ b/catalogue/client/table/table.html @@ -18,12 +18,12 @@

- {{_ "catalogueTable-addedBy"}} + {{_ "catalogueTable_addedBy"}} {{ api.getApiManagersByName }}
- {{_ "catalogueTable-added"}} + {{_ "catalogueTable_added"}} {{ api.relativeCreatedAt }} diff --git a/lib/helperFunctions/fileNameEndsWith.js b/core/helper_functions/file_name_ends_with.js similarity index 100% rename from lib/helperFunctions/fileNameEndsWith.js rename to core/helper_functions/file_name_ends_with.js diff --git a/lib/helperFunctions/validateSettings.js b/core/helper_functions/validate_settings.js similarity index 100% rename from lib/helperFunctions/validateSettings.js rename to core/helper_functions/validate_settings.js diff --git a/lib/i18n/en.i18n.json b/core/lib/i18n/en.i18n.json similarity index 86% rename from lib/i18n/en.i18n.json rename to core/lib/i18n/en.i18n.json index 0c56424cda..4d2d1d56b9 100644 --- a/lib/i18n/en.i18n.json +++ b/core/lib/i18n/en.i18n.json @@ -20,6 +20,7 @@ "apiBackend_Usage_Instructions_Note": "Note:", "apiBackend_Usage_Instructions_Note_Text": "You can find your API Key on your profile page.", "apiBackend_Usage_Instructions_Profile_Page_Link": "View profile.", + "apiBackendRating_anonymousError": "Please log in to rate this API", "apiBackends_Add_API_Title": "Add API", "apiBackends_AdvancedRequestsRewriting": "Advanced Requests Rewriting", "apiBackends_AdvancedRequestsRewriting_Help": "Modify the incoming requests made to the Umbrella front_end before they are passed on to your API backend", @@ -37,8 +38,6 @@ "apiBackends_Submit": "Submit", "apiBackends_Title_Help": "API's name", "apiBacklog_addBacklogItem_buttonText": "Add backlog item", - "apiBacklogItem_editBacklogItem-button": "Edit", - "apiBacklogItem_removeBacklogItem-button": "Remove", "apiBacklogList_noApiBacklogItemsFound": "No backlog items found for this API.", "apiBacklog_mainTitle": "Backlog", "apiBackendSelectPicker_selectAPI": "Select API", @@ -57,9 +56,8 @@ "branding_update": "Update", "branding_save": "Save", "branding_panel_title": "Project Branding", - "catalogue-AverageRating-Tooltip": "Average Rating", - "catalogue-Bookmark-Tooltip_NonUser": "Number of bookmarks. Sign in to bookmark.", - "catalogue-Bookmark-Tooltip_User": "Bookmark API", + "catalogue_bookmarkTooltip_nonUser": "Number of bookmarks. Sign in to bookmark.", + "catalogue_BookmarkTooltip_user": "Bookmark API", "catalogue_paginationButtons_next": "Next", "catalogue_paginationButtons_previous": "Previous", "catalogue_toolbar_filterOptions_myApis": "My APIs", @@ -75,9 +73,9 @@ "catalogue_toolbar_toggleCollapse": "Toggle toolbar", "catalogue_toolbar_viewMode_grid": "Grid", "catalogue_toolbar_viewMode_table": "Table", - "catalogueGrid-addedBy": "Added by", - "catalogueTable-added": "Added", - "catalogueTable-addedBy": "Added by", + "catalogueGrid_addedBy": "Added by", + "catalogueTable_added": "Added", + "catalogueTable_addedBy": "Added by", "catalogue_FilterButtons_My_APIs": "My APIs", "catalogue_FilterButtons_My_Bookmarks": "My Bookmarks", "catalogue_FilterButtons_Show_All": "Show All", @@ -118,6 +116,7 @@ "deleteApiBackendConfirmation_confirmDeleteNote": "NOTE:", "deleteApiBackendConfirmation_deleteButton": "Delete", "deleteApiBackendConfirmation_header": "Delete API", + "deleteApiBackendConfirmation_successMessage": "Successfully deleted API:", "delete_account": "Delete Account", "delete_account_warn": "There's no coming back from this one", "delete_account_warn2": "Are you sure you want to delete your account?", @@ -137,30 +136,12 @@ "documentation_Viewer_Title": "Viewer", "documentation_sdkGenerateButton": "SDK Generate", "documentation_tooltipSDKGeneratorButton": "With a valid swagger file, you can download an SDK of your preferred language using this wizard", - "editApiBackendForm-uploadLogo": "Upload logo", - "editApiMetadata_editApiMetadataForm_button": "Edit API Metadata", - "editApiMetadata_editApiMetadataForm_title": "Edit API Metadata", - "editApiMetadata_submitButtonText": "Submit", - "editApi_hints_api_balance_algorithm": "In case you have provided multiple Front-end : Back-end host pairs, choose the balancing algorithm using which umbrella should forward the requests to your api backend.", - "editApi_hints_api_key_verification_level": "Choose 'required' if API key is required to access your API", - "editApi_hints_api_name": "A name that describes your API", - "editApi_hints_append_query_string": "Add the parameters required by your API in key1=value1&key2=value2 format.
This place is best to add those parameters that is not mandatory for your API-users but your API needs them for providing meaningful data.", - "editApi_hints_backend_host": "Server where your API is hosted.", - "editApi_hints_backend_port": "Choose port for the backend host", - "editApi_hints_backend_protocol": "Choose the protocol used by your API (e.g. http or https)", - "editApi_hints_frontend_host": "Server where Umbrella is hosted.

If API Umbrella installed locally, enter localhost as your Backend host.", - "editApi_hints_http_basic_auth": "Does your api need a username and password for access? If yes, they must be specified here.", - "editApi_hints_importApiDocumentation": "If your documentation exists but is not available online, you can host it on APINF.
Upload your documentation in Swagger format here.", - "editApi_hints_require_https": "Choose 'required' if HTTPS is mandatory for accessing your apis.", - "editApi_hints_servers": "URL of the server that hosts the API.

The port on the server which exposes your API to internet.

You can add multiple servers if you want us to perform load balancing on your incoming requests", - "editApi_hints_set_headers": "If your API requires some specific headers to be set, they should be added here", - "editApi_hints_settings": "Define header values that will be set in the response regardless of whether the header is already set in the response.

For example, to force CORS headers on all responses:

'Access-Control-Allow-Origin: *'", - "editApi_hints_url_matches": "We recommend to have a unique URL Front-end prefix for your API so that it does not conflict with other existing APIs.
Apart from that, you can also segregate different sections of your API with different prefixes.
All the requests made to the 'Front-end host / Front-end prefix' will be re-written to 'Backend host / Backend prefix'

Frontend prefix: A prefix for your API, recognized by the Umbrella, e.g. /my_dev_api/

Backend prefix: Usually a part of your API's url, helpful to shorten the URL used for accessing your API, e.g. /apiv2/staging/experimental OR something as simple as '/'.", "editBacklogItem_modalTitle": "Edit backlog item", "editBacklogItem_submit_buttonText": "Save", "esData_notFound": "There are no API usage statistics available.", "favourite_Add": "Add bookmark", "favourite_Remove": "Remove bookmark", + "feedbackForm_successMessage": "Thank you! Your feedback has been successfully sent.", "feedback_feedbackForm_button": "Send feedback", "feedback_feedbackForm_description": "We welcome problem reports, feature ideas and general comments.", "feedback_feedbackForm_title": "Send feedback or report a problem", @@ -217,18 +198,21 @@ "homeHeader_signUp": "Sign Up", "homeHeader_toggleNavigation": "Toggle navigation", "homeFooter_dashboardLink_text": "Dashboard", + "importApiConfiguration_errorMessage": "Config file should be .YAML, .YML, .JSON or .TXT only.", "import_ApiConfiguration_Drop": "Drop file to here", "import_ApiConfiguration_File": "File:", "import_ApiConfiguration_Preview": "Preview:", + "mportApiConfiguration_jsonError_message": "Configuration does not look like correct JSON object.", "import_ApiConfiguration_Title": "Import API Configuration", "import_ApiConfiguration_Upload": "Upload", "import_ApiDocumentation_File": "Documentation Configuration File", + "importApiDocumentation_fileExtensionError_message": "Only .json and .yaml(.yml) files are supported.", + "importApiDocumentation_fileReadError_message": "Error when reading the file. Please check file contents for errors.", "import_ApiDocumentation_Title": "Upload documentation", "latestApiBackends_DateAdded": "Added %s", "latestApiBackends_Heading": "Latest APIs", "latestApiBackends_MoreInfo": "More info", "latestApiBackends_NotFound": "Nothing found.", - "manageApiBackends_deleteButton": "Delete", "manageApiDocumentationModalUploadButton": "Choose file", "manageApiDocumentationModal_AddedFile_Message": "Documentation file successfully uploaded!", "manageApiDocumentationModal_CreateDocumentation_CancelButton": "Cancel", @@ -247,13 +231,6 @@ "manageApiDocumentationModal_hints_documentation_link": "Link of the wiki / github page / web resource where the documentation of your API is located", "manageApiDocumentationModal_hints_uploadApiDocumentation": "You can also choose to create a new documentation for your APIs using swagger at our own server", "manageApiDocumentationModal_openDocumentationEditor": "Open API documentation editor", - "manage_ApiBackends_Backend": "Backend:", - "manage_ApiBackends_Edit": "Edit", - "manage_ApiBackends_Frontend": "Frontend:", - "manage_ApiBackends_Matches": "URL Matches", - "manage_ApiBackends_Rewrite": "Rewrite to", - "manage_ApiBackends_Title": "My managed APIs", - "manage_ApiBackends_View": "View", "masterLayout_sidebar_APIBackends": "API Backends", "masterLayout_sidebar_AddAPIBackend": "Add API Backend", "masterLayout_sidebar_Analytics": "Analytics", @@ -286,6 +263,7 @@ "proxyBackendForm_successMessage": "Settings saved.", "proxyItem_editProxy": "Edit", "proxyItem_removeProxy": "Remove", + "publishApiBackendOnApiUmbrella_successMessage": "API Backend successfully published.", "removeProxy_modalLabel": "Are you sure that you want to remove proxy?", "removeProxy_confirmRemoveProxy": "Yes, remove", "removeProxy_cancelRemove": "Cancel", @@ -414,22 +392,47 @@ } }, "settings": { - "apiUmbrella": { + "apiDocumentationEditor": { + "label": "API Documentation Editor", + "enabled": { + "label": "Enabled" + }, "host": { "label": "Host", - "placeholder": "https://example.com/" + "placeholder": "https://editor.example.com/" + } + }, + "mail": { + "label": "Mail (SMTP)", + "enabled": { + "label": "Enabled" + }, + "username": { + "label": "Username" + }, + "password": { + "label": "Password" }, - "apiKey": { - "label": "API Key", - "placeholder": "xxx" + "toEmail": { + "label": "To email" + } + }, + "githubConfiguration": { + "label": "Github configuration", + "clientId": { + "label": "Client ID" }, - "authToken": { - "label": "Auth Token", - "placeholder": "xxx" + "secret": { + "label": "Secret" + } + }, + "sdkCodeGenerator": { + "label": "SDK Generator", + "enabled": { + "label": "Enabled" }, - "baseUrl": { - "label": "Base URL", - "placeholder": "https://example.com/api-umbrella/" + "host": { + "label": "Host" } } } @@ -478,13 +481,14 @@ "umbrella_createuser_error": "Failed to create user on API Umbrella.", "umbrella_notdefined_error": "API Umbrella not defined.", "updatePassword_submitButton_text": "Change Password", + "updatePasswordForm_successMessage": "Password updated.", "uploadApiLogoButton": "Upload logo", "uploadApiLogo_confirm_delete": "Are you sure you want to delete this logo?", "uploadApiLogo_successfully_deleted": "Logo successfully deleted!", "uploadProjectLogo_confirm_delete": "Are you sure you want to delete your project logo?", "uploadProjectLogo_acceptedExtensions": "Only .jpg, .jpeg, .png, .gif are accepted.", "uploadProjectLogo_successfully_uploaded": "Your project logo successfully uploaded!", - "uploadProjectLogo_successfully_deleted": "Your ptoject logo successfully deleted!", + "uploadProjectLogo_successfully_deleted": "Your project logo successfully deleted!", "userMenu_account": "Account", "userMenu_branding": "Branding", "userMenu_profile": "Profile", @@ -506,6 +510,7 @@ "viewApiBackendSettigs_saveButton_text": "Save", "viewApiBackendSettings_deleteApiText": "This action cannot be undone. The API Backend and all its related information, i.e. metadata, documentation, API backlog items and feedback will be removed.", "viewApiBackendSettings_deleteApiTitle": "Delete the API", + "viewApiBackendSettings_uploadLogo_heading": "Upload logo", "viewApiBackendSettings_uploadLogoText": "You can upload a logo for your API. The logo will appear in the catalogue and on the single API page.", "viewApiBackendStatus_statusMessage_ClientError": "Client error.", "viewApiBackendStatus_statusMessage_ErrorCodeText": "Status code:", diff --git a/lib/i18n/fi.i18n.json b/core/lib/i18n/fi.i18n.json similarity index 96% rename from lib/i18n/fi.i18n.json rename to core/lib/i18n/fi.i18n.json index abfe9ba323..3cc3755582 100644 --- a/lib/i18n/fi.i18n.json +++ b/core/lib/i18n/fi.i18n.json @@ -76,13 +76,6 @@ "import_ApiConfiguration_Upload": "Lataa palvelimelle", "import_ApiDocumentation_Title": "Lataa dokumentaatio palvelimelle", "import_ApiDocumentation_File": "Määrittelytiedosto dokumentaatiolle", - "manage_ApiBackends_Title": "Hallinnoimani rajapinnat", - "manage_ApiBackends_Rewrite": "Kirjoita uudelleen", - "manage_ApiBackends_Matches": "Vastaavat URL:t", - "manage_ApiBackends_Backend": "Taustajärjestelmä:", - "manage_ApiBackends_Frontend": "Frontend:", - "manage_ApiBackends_View": "Tarkastele", - "manage_ApiBackends_Edit": "Muokkaa", "apiBackend_Status_Title": "Tila", "apiBackend_Status_Updated": "Päivitetty:", "apiBackend_Status_Checking": "API:n tilaa tarkistetaan. Odota hetki...", @@ -186,8 +179,6 @@ "apiBacklog_mainTitle": "Tehtävälista", "apiBacklogForm_addBacklogItem_button": "Lisää uusi tehtävä", "apiBacklogList_noApiBacklogItemsFound": "Ei löydetty tehtäviä tälle rajapinnalle.", - "apiBacklogItem_removeBacklogItem-button": "Poista", - "apiBacklogItem_editBacklogItem-button": "Muokkaa", "statusCheckTitle": "Tila", "statusCheckUpdated": "Päivitetty:", "statusCheckJustNow": "Juuri äsken.", diff --git a/lib/_config/sAlert.js b/core/lib/sAlert_configuration.js similarity index 100% rename from lib/_config/sAlert.js rename to core/lib/sAlert_configuration.js diff --git a/documentation/client/codegenerator/autoform.js b/documentation/client/codegenerator/autoform.js index a4de5ae8f5..1440e1cad7 100644 --- a/documentation/client/codegenerator/autoform.js +++ b/documentation/client/codegenerator/autoform.js @@ -42,7 +42,11 @@ AutoForm.addHooks('downloadSDK', { HTTP.post(url, { data: options }, function (error, result) { // If url is incorrect if (result === undefined) { - FlashMessages.sendError(TAPi18n.__('sdkCodeGeneratorModal_errorTextInvalidHost')); + // Get error message translation + const message = TAPi18n.__('sdkCodeGeneratorModal_errorTextInvalidHost'); + + // Alert user of error + sAlert.error(message); } else { // Get information from Swagger API response const response = JSON.parse(result.content); @@ -55,7 +59,12 @@ AutoForm.addHooks('downloadSDK', { window.location.href = response.link; } else { // Otherwise show an error message - FlashMessages.sendError(TAPi18n.__('sdkCodeGeneratorModal_errorText')); + + // Get error message translation + const message = TAPi18n.__('sdkCodeGeneratorModal_errorText'); + + // Alert user of error + sAlert.error(message); } } $('button').removeAttr('disabled'); diff --git a/documentation/client/codegenerator/codegenerator.html b/documentation/client/codegenerator/codegenerator.html index b92092807c..f38dec9b1f 100644 --- a/documentation/client/codegenerator/codegenerator.html +++ b/documentation/client/codegenerator/codegenerator.html @@ -12,13 +12,13 @@

- {{> flashMessages}} - \ No newline at end of file + diff --git a/documentation/client/manage/autoform.js b/documentation/client/manage/autoform.js index f54d9531d4..5b65473904 100644 --- a/documentation/client/manage/autoform.js +++ b/documentation/client/manage/autoform.js @@ -3,9 +3,9 @@ AutoForm.hooks({ onSuccess () { // Get success message translation const message = TAPi18n.__('manageApiDocumentationModal_LinkField_Updated_Message'); - + // Alert user of success sAlert.success(message); }, - } -}); \ No newline at end of file + }, +}); diff --git a/documentation/client/manage/manage.js b/documentation/client/manage/manage.js index 6270093bd3..88c5e6cf94 100644 --- a/documentation/client/manage/manage.js +++ b/documentation/client/manage/manage.js @@ -4,36 +4,37 @@ import { Settings } from '/settings/collection'; Template.manageApiDocumentationModal.onCreated(function () { const instance = this; - + // Initialize help texts const helpTexts = { - 'documentation_link': { + documentation_link: { message: TAPi18n.__('manageApiDocumentationModal_hints_documentation_link'), options: { placement: 'left', }, }, - 'uploadApiDocumentation': { + uploadApiDocumentation: { message: TAPi18n.__('manageApiDocumentationModal_hints_uploadApiDocumentation'), options: { placement: 'left', }, }, - 'documentation_editor_create_file': { + documentation_editor_create_file: { message: TAPi18n.__('manageApiDocumentationModal_hints_createApiDocumentation'), options: { placement: 'left', }, }, }; + InlineHelp.initHelp(helpTexts); - + instance.autorun(function () { const api = Apis.findOne(instance.data.api._id); // Save apibackend id Session.set('api', api); }); - + // Subscribe to documentation editor settings instance.subscribe('singleSetting', 'apiDocumentationEditor'); }); @@ -45,24 +46,36 @@ Template.manageApiDocumentationModal.onDestroyed(function () { Template.manageApiDocumentationModal.events({ 'click .delete-documentation': function (event, instance) { + // Get confirmation message translation + const message = TAPi18n.__('manageApiDocumentationModal_DeletedFile_ConfirmationMessage'); + // Show confirmation dialog to user - const confirmation = confirm(TAPi18n.__('manageApiDocumentationModal_DeletedFile_ConfirmationMessage')); - + const confirmation = confirm(message); + // Check if user clicked "OK" if (confirmation === true) { // Get currentApiBackend documentationFileId const documentationFileId = this.api.documentationFileId; - + // Convert to Mongo ObjectID const objectId = new Mongo.Collection.ObjectID(documentationFileId); - + // Remove documentation object DocumentationFiles.remove(objectId); - + // Remove documenation file id field Apis.update(instance.data.api._id, { $unset: { documentationFileId: '' } }); - +<<<<<<< HEAD + + // Get deletion success message translation + const message = TAPi18n.__('manageApiDocumentationModal_DeletedFile_Message'); + + // Alert user of successful deletion + sAlert.success(message); +======= + sAlert.success(TAPi18n.__('manageApiDocumentationModal_DeletedFile_Message')); +>>>>>>> 8a78101cf5b33ffae10ffc91ecb53f09517c5d37 } }, 'click #save-documentation-link': function (event, instance) { @@ -79,15 +92,15 @@ Template.manageApiDocumentationModal.events({ Template.manageApiDocumentationModal.helpers({ documentationFile () { const api = Session.get('api'); - + const documentationFileId = api.documentationFileId; - + // Convert to Mongo ObjectID const objectId = new Mongo.Collection.ObjectID(documentationFileId); - + // Get documentation file Object const documentationFile = DocumentationFiles.findOne(objectId); - + // Check if documentation file is available if (documentationFile) { return documentationFile; @@ -96,7 +109,7 @@ Template.manageApiDocumentationModal.helpers({ apiDocumentationEditorIsEnabled () { // Get settings const settings = Settings.findOne(); - + // Check settings exists, editor is enabled and host setting exists if ( settings && diff --git a/documentation/client/view/resumable.js b/documentation/client/view/resumable.js index b53b9305fa..a323da93d2 100644 --- a/documentation/client/view/resumable.js +++ b/documentation/client/view/resumable.js @@ -1,6 +1,6 @@ import { DocumentationFiles } from '/documentation/collection/collection'; import { Apis } from '/apis/collection'; -import { fileNameEndsWith } from '/lib/helperFunctions/fileNameEndsWith'; +import { fileNameEndsWith } from '/core/helper_functions/file_name_ends_with'; Meteor.startup(function () { DocumentationFiles.resumable.on('fileAdded', function (file) { @@ -27,16 +27,29 @@ Meteor.startup(function () { // Update documenation file id field Apis.update(api._id, { $set: { documentationFileId } }); - sAlert.success(TAPi18n.__('manageApiDocumentationModal_AddedFile_Message')); + // Get success message translation + const message = TAPi18n.__('manageApiDocumentationModal_AddedFile_Message'); + + // Alert user of success + sAlert.success(message); return DocumentationFiles.resumable.upload(); } else { - sAlert.error(TAPi18n.__('manageApiDocumentationModal_FileType_Message')); + // Get error message translation + const message = TAPi18n.__('manageApiDocumentationModal_FileType_Message'); + + // Alert user of error + sAlert.error(message); } }); } else { // Inform user about file size Limit - sAlert.warning(TAPi18n.__('manageApiDocumentationModal_SizeLimit_Message')); + + // Get file size limit message translation + const message = TAPi18n.__('manageApiDocumentationModal_SizeLimit_Message'); + + // Alert user of file size warning + sAlert.warning(message); } }); }); diff --git a/server/publish/apiDocumentation.js b/documentation/collection/server/publications.js similarity index 100% rename from server/publish/apiDocumentation.js rename to documentation/collection/server/publications.js diff --git a/feedback/client/form/autoform.js b/feedback/client/form/autoform.js index 5a211c3c0e..8ff7c3702a 100644 --- a/feedback/client/form/autoform.js +++ b/feedback/client/form/autoform.js @@ -8,7 +8,11 @@ AutoForm.hooks({ }, }, onSuccess () { - sAlert.success('Thank you! Your feedback has been successfully sent.'); + // Get success message translation + const message = TAPi18n.__('feedbackForm_successMessage'); + + // Alert user of success + sAlert.success(message); }, }, }); diff --git a/home/client/body/homeBody.js b/home/client/body/homeBody.js index 9c83766727..711908d18f 100755 --- a/home/client/body/homeBody.js +++ b/home/client/body/homeBody.js @@ -1,4 +1,4 @@ -import { contactEmailValid } from '/lib/helperFunctions/validateSettings'; +import { contactEmailValid } from '/core/helper_functions/validate_settings'; import { Settings } from '/settings/collection'; Template.homeBody.onCreated(function () { diff --git a/home/client/contact/autoform.js b/home/client/contact/autoform.js index ab1cf0d58c..6f01f343c4 100755 --- a/home/client/contact/autoform.js +++ b/home/client/contact/autoform.js @@ -10,10 +10,10 @@ AutoForm.hooks({ }, onSuccess () { // Get translated success message - const successMessage = TAPi18n.__('contactForm_successMessage'); + const message = TAPi18n.__('contactForm_successMessage'); // Alert user of success - sAlert.success(successMessage); + sAlert.success(message); }, }, }); diff --git a/home/client/contact/contact.html b/home/client/contact/contact.html index b0405ca5c9..359e679dc0 100755 --- a/home/client/contact/contact.html +++ b/home/client/contact/contact.html @@ -4,7 +4,6 @@ {{> afQuickField name="name"}} {{> afQuickField name="email"}} {{> afQuickField name="message"}} - {{> flashMessages}}
- {{> flashMessages}} diff --git a/both/collections/apiUmbrellaAdmins.js b/proxies/api_umbrella/collections/api_umbrella_admins.js similarity index 50% rename from both/collections/apiUmbrellaAdmins.js rename to proxies/api_umbrella/collections/api_umbrella_admins.js index de87fbe00d..c8d3ccfb51 100644 --- a/both/collections/apiUmbrellaAdmins.js +++ b/proxies/api_umbrella/collections/api_umbrella_admins.js @@ -1,58 +1,58 @@ ApiUmbrellaAdmins = new Mongo.Collection('apiUmbrellaAdmins'); -Schemas.ApiUmbrellaAdminsSchema = new SimpleSchema({ +const ApiUmbrellaAdminsSchema = new SimpleSchema({ id: { type: String, - optional: true + optional: true, }, username: { type: String, - optional: true + optional: true, }, email: { type: String, - optional: true + optional: true, }, name: { type: String, - optional: true + optional: true, }, - notes:{ + notes: { type: String, - optional: true + optional: true, }, - superuser:{ + superuser: { type: Boolean, - optional: true + optional: true, }, - authentication_token:{ + authentication_token: { type: String, - optional: true - }, - last_sign_in_provider:{ + optional: true, + }, + last_sign_in_provider: { type: String, - optional: true + optional: true, }, sign_in_count: { type: Number, - optional: true + optional: true, }, current_sign_in_at: { - type: Date, - optional: true + type: Date, + optional: true, }, last_sign_in_at: { type: Date, - optional: true + optional: true, }, current_sign_in_ip: { type: String, - optional: true + optional: true, }, last_sign_in_ip: { type: String, - optional: true - } + optional: true, + }, }); -ApiUmbrellaAdmins.attachSchema(Schemas.ApiUmbrellaAdminsSchema); +ApiUmbrellaAdmins.attachSchema(ApiUmbrellaAdminsSchema); diff --git a/both/collections/apiUmbrellaUsers.js b/proxies/api_umbrella/collections/api_umbrella_users.js similarity index 61% rename from both/collections/apiUmbrellaUsers.js rename to proxies/api_umbrella/collections/api_umbrella_users.js index 6976abe6bf..f31e80ff6e 100644 --- a/both/collections/apiUmbrellaUsers.js +++ b/proxies/api_umbrella/collections/api_umbrella_users.js @@ -1,72 +1,72 @@ ApiUmbrellaUsers = new Mongo.Collection('apiUmbrellaUsers'); -Schemas.ApiUmbrellaUsersSchema = new SimpleSchema({ +const ApiUmbrellaUsersSchema = new SimpleSchema({ id: { type: String, - optional: true + optional: true, }, api_key: { type: String, - optional: true + optional: true, }, created_at: { type: Date, - optional: true + optional: true, }, first_name: { type: String, - optional: true + optional: true, }, last_name: { type: String, - optional: true + optional: true, }, email: { type: String, - optional: true + optional: true, }, email_verified: { type: Boolean, - optional: true + optional: true, }, website: { type: String, - optional: true + optional: true, }, registration_source: { type: String, - optional: true + optional: true, }, throttle_by_ip: { type: Boolean, - optional: true + optional: true, }, disabled_at: { type: Date, - optional: true + optional: true, }, roles: { type: [String], - optional: true + optional: true, }, userId: { type: String, label: 'User', optional: true, autoform: { - options: function() { + options () { // Get all Meteor users as array - var users = Meteor.users.find().fetch(); + const users = Meteor.users.find().fetch(); // Create an array of label value pairs for autoform select - return _.map(users, function(user) { + return _.map(users, function (user) { return { label: user.emails[0].address, - value: user._id + value: user._id, }; }); - } - } - } + }, + }, + }, }); -ApiUmbrellaUsers.attachSchema(Schemas.ApiUmbrellaUsersSchema); +ApiUmbrellaUsers.attachSchema(ApiUmbrellaUsersSchema); diff --git a/server/publish/apiUmbrellaAdmins.js b/proxies/api_umbrella/collections/server/api_umbrella_admins_publications.js similarity index 100% rename from server/publish/apiUmbrellaAdmins.js rename to proxies/api_umbrella/collections/server/api_umbrella_admins_publications.js diff --git a/server/publish/apiUmbrellaUsers.js b/proxies/api_umbrella/collections/server/api_umbrella_users_publications.js similarity index 100% rename from server/publish/apiUmbrellaUsers.js rename to proxies/api_umbrella/collections/server/api_umbrella_users_publications.js diff --git a/proxy_backends/client/form/autoform.js b/proxy_backends/client/form/autoform.js index 9eae029555..901b4e7504 100644 --- a/proxy_backends/client/form/autoform.js +++ b/proxy_backends/client/form/autoform.js @@ -2,10 +2,10 @@ AutoForm.hooks({ proxyBackendForm: { onSuccess () { // Get success message translation - const successMessage = TAPi18n.__('proxyBackendForm_successMessage'); + const message = TAPi18n.__('proxyBackendForm_successMessage'); // Alert the user of success - sAlert.success(successMessage); + sAlert.success(message); }, }, }); diff --git a/ratings/client/rating.js b/ratings/client/rating.js index 2d56a71621..9450a930ea 100644 --- a/ratings/client/rating.js +++ b/ratings/client/rating.js @@ -60,10 +60,10 @@ Template.apiBackendRating.events({ // Make sure there is a Meteor user ID for voting if (Meteor.userId() === null) { // Get translated user message - const userMessage = TAPi18n.__('api-backend-rating-anonymous'); + const message = TAPi18n.__('apiBackendRating_anonymousError'); // Alert the user that they must log in - sAlert.error(userMessage); + sAlert.error(message); return false; } diff --git a/server/githubConfiguration.js b/server/githubConfiguration.js deleted file mode 100644 index 37f2578fbf..0000000000 --- a/server/githubConfiguration.js +++ /dev/null @@ -1,31 +0,0 @@ -import { githubSettingsValid } from '/lib/helperFunctions/validateSettings'; -import { Settings } from '/settings/collection'; - -// If settings are already in Meteor.settings -try { - const settings = Settings.findOne(); - - // Check if github settings are valid - if (githubSettingsValid(settings)) { - ServiceConfiguration.configurations.remove({ - // removing existing configurations - service: 'github', - }); - - ServiceConfiguration.configurations.insert({ - /* extend settings.json with Client ID and Client Secret: - "githubConfiguration": { - "clientId" : "xxxx", - "secret" : "xxxx" - }*/ - service: 'github', - clientId: settings.githubConfiguration.clientId, - secret: settings.githubConfiguration.secret, - - }); - } -} -// otherwise show an error -catch (error) { - console.log(error); -} diff --git a/settings/client/autoform.js b/settings/client/autoform.js index d433c3d84f..0b88823b43 100644 --- a/settings/client/autoform.js +++ b/settings/client/autoform.js @@ -2,10 +2,10 @@ AutoForm.hooks({ settings: { onSuccess () { // Get settings form success message translation - const successMessage = TAPi18n.__('settings_successMessage'); + const message = TAPi18n.__('settings_successMessage'); // Alert the user of successful save - sAlert.success(successMessage); + sAlert.success(message); }, }, }); diff --git a/settings/client/settings.html b/settings/client/settings.html index 5f5fae7df3..9abb907e4f 100644 --- a/settings/client/settings.html +++ b/settings/client/settings.html @@ -53,8 +53,6 @@

{{_ "settings_github"}}

- - {{> flashMessages}} {{/autoForm}} diff --git a/settings/collection/schema.js b/settings/collection/schema.js index b5cbb74a36..e53476e108 100644 --- a/settings/collection/schema.js +++ b/settings/collection/schema.js @@ -1,10 +1,6 @@ import { Settings } from './'; Settings.schema = new SimpleSchema({ - apinf: { - type: Object, - optional: true, - }, apiDocumentationEditor: { type: Object, optional: true, @@ -16,7 +12,6 @@ Settings.schema = new SimpleSchema({ 'apiDocumentationEditor.host': { type: String, regEx: SimpleSchema.RegEx.Url, - label: 'Host', optional: true, autoform: { placeholder: 'http://editor.example.com/', @@ -111,10 +106,6 @@ Settings.schema = new SimpleSchema({ placeholder: 'xxx', }, }, - initialSetupComplete: { - type: Boolean, - optional: true, - }, sdkCodeGenerator: { type: Object, optional: true, @@ -126,7 +117,6 @@ Settings.schema = new SimpleSchema({ 'sdkCodeGenerator.host': { type: String, regEx: SimpleSchema.RegEx.Url, - label: 'Host', optional: true, autoform: { placeholder: 'https://generator.example.com/', @@ -144,6 +134,6 @@ Settings.schema = new SimpleSchema({ }); // Enable translations (i18n) -Settings.schema.i18n('schemas.settings.apiUmbrella'); +Settings.schema.i18n('schemas.settings'); Settings.attachSchema(Settings.schema); diff --git a/settings/server/github_configuration.js b/settings/server/github_configuration.js new file mode 100644 index 0000000000..3240d32b22 --- /dev/null +++ b/settings/server/github_configuration.js @@ -0,0 +1,33 @@ +import { githubSettingsValid } from '/core/helper_functions/validate_settings'; +import { Settings } from '../collection'; + +export const enableGithubAuthentication = () => { + // If settings are already in Meteor.settings + try { + const settings = Settings.findOne(); + + // Check if github settings are valid + if (githubSettingsValid(settings)) { + ServiceConfiguration.configurations.remove({ + // removing existing configurations + service: 'github', + }); + + ServiceConfiguration.configurations.insert({ + /* extend settings.json with Client ID and Client Secret: + "githubConfiguration": { + "clientId" : "xxxx", + "secret" : "xxxx" + }*/ + service: 'github', + clientId: settings.githubConfiguration.clientId, + secret: settings.githubConfiguration.secret, + + }); + } + } + // otherwise show an error + catch (error) { + console.log(error); + } +}; diff --git a/settings/server/oauth_configuration.js b/settings/server/oauth_configuration.js new file mode 100644 index 0000000000..18a556a3ba --- /dev/null +++ b/settings/server/oauth_configuration.js @@ -0,0 +1,13 @@ +// TODO: refactor this to use Settings collection +// TODO: remove from Meteor.startup, run when Settings updated +Meteor.startup(function () { + if (Meteor.settings && Meteor.settings.serviceConfigurations) { + return _.each(Meteor.settings.serviceConfigurations, function (config, service) { + return ServiceConfiguration.configurations.upsert({ + service, + }, { + $set: config, + }); + }); + } +}); diff --git a/server/smtp.js b/settings/server/smtp.js similarity index 85% rename from server/smtp.js rename to settings/server/smtp.js index f73307ea2d..97ca2c21be 100644 --- a/server/smtp.js +++ b/settings/server/smtp.js @@ -1,5 +1,5 @@ -import { mailSettingsValid } from '/lib/helperFunctions/validateSettings'; -import { Settings } from '/settings/collection'; +import { mailSettingsValid } from '/core/helper_functions/validate_settings'; +import { Settings } from '../collection'; Meteor.startup(function () { /* extend settings.json with username and password: diff --git a/users/client/account/password/autoform.js b/users/client/account/password/autoform.js index 9e25370d5e..99551c31e8 100644 --- a/users/client/account/password/autoform.js +++ b/users/client/account/password/autoform.js @@ -3,16 +3,20 @@ AutoForm.hooks({ onSubmit (insertDoc, updateDoc, currentDoc) { this.event.preventDefault(); const instance = this; - Accounts.changePassword(insertDoc.old, insertDoc.new, function (e) { + Accounts.changePassword(insertDoc.old, insertDoc.new, function (error) { $('.btn-primary').attr('disabled', null); - if (e) { + if (error) { // Alert the user of failure - sAlert.error(e.message); - instance.done(e.message); + sAlert.error(error.message); + instance.done(error.message); } else { + // Get password update success message translation + const message = TAPi18n.__('updatePasswordForm_successMessage'); + // Alert the user of success - sAlert.success('Password Updated'); - instance.done('Password Updated'); + sAlert.success(message); + instance.done(message); + // Clear the form AutoForm.resetForm('updatePassword'); } diff --git a/users/client/profile/profile.js b/users/client/profile/profile.js index d34c975b1b..64369b7bab 100644 --- a/users/client/profile/profile.js +++ b/users/client/profile/profile.js @@ -1,8 +1,11 @@ AutoForm.hooks({ updateProfile: { onSuccess (operation, result, template) { - const profileUpdatedMsg = TAPi18n.__('profile_updatedSuccess'); - return sAlert.success(profileUpdatedMsg); + // Get update success message translation + const message = TAPi18n.__('profile_updatedSuccess'); + + // Alert user of success + sAlert.success(message); }, onError () { this.addStickyValidationError('username', 'usernameTaken'); @@ -20,8 +23,11 @@ Template.profile.rendered = function () { if (currentUser) { // Ask user to set username if it is not set. if (!currentUser.username) { - const setUsernameMsg = TAPi18n.__('profile-setUsername'); - sAlert.info(setUsernameMsg); + // Get username 'update needed' message + const message = TAPi18n.__('profile_setUsername'); + + // Alert user of update needed + sAlert.info(message); } } }; diff --git a/users/collection/roles_schema.js b/users/collection/roles_schema.js new file mode 100644 index 0000000000..84edc253b9 --- /dev/null +++ b/users/collection/roles_schema.js @@ -0,0 +1,7 @@ +const RolesSchema = new SimpleSchema({ + name: { + type: String, + }, +}); + +Meteor.roles.attachSchema(RolesSchema); diff --git a/server/publish/user.js b/users/collection/server/publications.js similarity index 100% rename from server/publish/user.js rename to users/collection/server/publications.js diff --git a/users/collection/users_permissions.js b/users/collection/users_permissions.js new file mode 100644 index 0000000000..f5da67d257 --- /dev/null +++ b/users/collection/users_permissions.js @@ -0,0 +1,8 @@ +Meteor.users.allow({ + update (currentUserId, user) { + // Only allow user to update own username + if (currentUserId === user._id) { + return true; + } + }, +}); diff --git a/users/collection/users_schema.js b/users/collection/users_schema.js new file mode 100644 index 0000000000..c207814a0b --- /dev/null +++ b/users/collection/users_schema.js @@ -0,0 +1,65 @@ +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; + +const UserProfileSchema = new SimpleSchema({ + name: { + type: String, + optional: true, + }, + company: { + type: String, + optional: true, + }, +}); +// Username must be 3-15 alphanumeric string with hyphens allowed. +const UsernameRegEx = /^[a-z0-9A-Z_\-]{3,15}$/; + +const UserSchema = new SimpleSchema({ + username: { + type: String, + regEx: UsernameRegEx, + optional: true, + }, + apiUmbrellaUserId: { + type: String, + optional: true, + }, + emails: { + type: [Object], + optional: false, + }, + 'emails.$.address': { + type: String, + regEx: SimpleSchema.RegEx.Email, + }, + 'emails.$.verified': { + type: Boolean, + }, + createdAt: { + type: Date, + }, + profile: { + type: UserProfileSchema, + }, + services: { + type: Object, + optional: true, + blackbox: true, + }, + roles: { + type: [String], + blackbox: true, + optional: true, + }, +}); + +// Fetch username invalid message +const usernameInvalid = TAPi18n.__('profile-usernameInvalid'); + +// Define custom validation error messages +UserProfileSchema.messages({ + 'regEx username': [ + { exp: UsernameRegEx, msg: usernameInvalid }, + ], +}); + +Meteor.users.attachSchema(UserSchema); diff --git a/both/collections/_messages.js b/users/collection/users_schema_messages.js similarity index 100% rename from both/collections/_messages.js rename to users/collection/users_schema_messages.js diff --git a/server/accounts.js b/users/server/accounts_hooks.js similarity index 100% rename from server/accounts.js rename to users/server/accounts_hooks.js