diff --git a/assets/javascripts/discourse/controllers/admin-wizards-api.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-api.js.es6 index 7306012e..30fa0130 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-api.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-api.js.es6 @@ -165,6 +165,19 @@ export default Ember.Controller.extend({ }); } }).finally(() => this.set('updating', false)); + }, + + clearLogs() { + ajax(`/admin/wizards/apis/logs/${name.underscore()}`, { + type: 'DELETE' + }).catch(popupAjaxError) + .then(result => { + if (result.success) { + this.transitionToRoute('adminWizardsApis').then(() => { + this.send('refreshModel'); + }); + } + }).finally(() => this.set('updating', false)); } } }); diff --git a/assets/javascripts/discourse/models/custom-wizard-api.js.es6 b/assets/javascripts/discourse/models/custom-wizard-api.js.es6 index 791a153a..b335b88a 100644 --- a/assets/javascripts/discourse/models/custom-wizard-api.js.es6 +++ b/assets/javascripts/discourse/models/custom-wizard-api.js.es6 @@ -35,7 +35,8 @@ CustomWizardApi.reopenClass({ tokenExpiresAt: authorization.token_expires_at, tokenRefreshAt: authorization.token_refresh_at, endpoints: Ember.A(endpoints), - isNew: params.isNew + isNew: params.isNew, + log: params.log }); return api; diff --git a/assets/javascripts/discourse/templates/admin-wizards-api.hbs b/assets/javascripts/discourse/templates/admin-wizards-api.hbs index 0ed5766e..04ffb4fd 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-api.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-api.hbs @@ -237,3 +237,29 @@ {{/if}} + +
+ {{i18n 'admin.wizard.api.log.label'}} + {{d-button action='clearLogs' + icon='trash-alt' + class='clear-logs'}} +
+ +
+
+ + + + + + {{#each api.log as |logentry|}} + + + + + + + {{/each}} +
DatetimeStatusEndpointError
{{logentry.time}}{{logentry.status}}{{logentry.endpoint_url}}{{logentry.error}}
+
+
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 8062302d..86423497 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -184,6 +184,9 @@ en: method: "Select a method" url: "Enter a url" + log: + label: "Logs" + wizard_js: location: name: diff --git a/controllers/api.rb b/controllers/api.rb index 524f4e84..05075c12 100644 --- a/controllers/api.rb +++ b/controllers/api.rb @@ -57,11 +57,17 @@ class CustomWizard::ApiController < ::ApplicationController CustomWizard::Api.remove(api_params[:name]) CustomWizard::Api::Authorization.remove(api_params[:name]) CustomWizard::Api::Endpoint.remove(api_params[:name]) + CustomWizard::Api::LogEntry.clear(api_params[:name]) end render json: success_json end + def clearlogs + CustomWizard::Api::LogEntry.clear(api_params[:name]) + render json: success_json + end + def redirect params.require(:name) params.require(:code) diff --git a/lib/api/endpoint.rb b/lib/api/endpoint.rb index fc378df6..356687e7 100644 --- a/lib/api/endpoint.rb +++ b/lib/api/endpoint.rb @@ -87,8 +87,13 @@ class CustomWizard::Api::Endpoint begin response = connection.request(params) + log_params = {time: Time.now, status: 'SUCCESS', endpoint_url: endpoint.url, error: ""} + CustomWizard::Api::LogEntry.set(api_name, log_params) return JSON.parse(response.body) rescue + # TODO: improve error detail + log_params = {time: Time.now, status: 'FAILURE', endpoint_url: endpoint.url, error: "API request failed"} + CustomWizard::Api::LogEntry.set(api_name, log_params) return JSON.parse "[{\"error\":\"API request failed\"}]" end end diff --git a/lib/api/logentry.rb b/lib/api/logentry.rb new file mode 100644 index 00000000..083262aa --- /dev/null +++ b/lib/api/logentry.rb @@ -0,0 +1,69 @@ +class CustomWizard::Api::LogEntry + include ActiveModel::SerializerSupport + + attr_accessor :log_id, + :time, + :status, + :endpoint_url, + :error + + def initialize(api_name, data={}) + @api_name = api_name + + data.each do |k, v| + self.send "#{k}=", v if self.respond_to?(k) + end + end + + def self.set(api_name, new_data) + if new_data['log_id'] + data = self.get(api_name, new_data['log_id'], data_only: true) + log_id = new_data['log_id'] + else + data = {} + log_id = SecureRandom.hex(3) + end + + new_data.each do |k, v| + data[k.to_sym] = v + end + + PluginStore.set("custom_wizard_api_#{api_name}", "log_#{log_id}", data) + + self.get(api_name, log_id) + end + + def self.get(api_name, log_id, opts={}) + return nil if !log_id + + if data = PluginStore.get("custom_wizard_api_#{api_name}", "log_#{log_id}") + if opts[:data_only] + data + else + data[:log_id] = log_id + self.new(api_name, data) + end + else + nil + end + end + + def self.remove(api_name) + PluginStoreRow.where("plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'").destroy_all + end + + def self.list(api_name) + PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'") + .map do |record| + api_name = record['plugin_name'].sub("custom_wizard_api_", "") + data = ::JSON.parse(record['value']) + data[:log_id] = record['key'].split('_').last + self.new(api_name, data) + end + end + + def self.clear(api_name) + PluginStoreRow.where("plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'").destroy_all + end + +end diff --git a/plugin.rb b/plugin.rb index da45683d..588689e3 100644 --- a/plugin.rb +++ b/plugin.rb @@ -72,6 +72,7 @@ after_initialize do get 'admin/wizards/apis/:name' => 'api#find' put 'admin/wizards/apis/:name' => 'api#save' delete 'admin/wizards/apis/:name' => 'api#remove' + delete 'admin/wizards/apis/logs/:name' => 'api#clearlogs' get 'admin/wizards/apis/:name/redirect' => 'api#redirect' end end @@ -92,12 +93,14 @@ after_initialize do load File.expand_path('../lib/api/api.rb', __FILE__) load File.expand_path('../lib/api/authorization.rb', __FILE__) load File.expand_path('../lib/api/endpoint.rb', __FILE__) + load File.expand_path('../lib/api/logentry.rb', __FILE__) load File.expand_path('../controllers/api.rb', __FILE__) load File.expand_path('../serializers/api/api_serializer.rb', __FILE__) load File.expand_path('../serializers/api/authorization_serializer.rb', __FILE__) load File.expand_path('../serializers/api/basic_api_serializer.rb', __FILE__) load File.expand_path('../serializers/api/endpoint_serializer.rb', __FILE__) load File.expand_path('../serializers/api/basic_endpoint_serializer.rb', __FILE__) + load File.expand_path('../serializers/api/log_serializer.rb', __FILE__) ::UsersController.class_eval do def wizard_path diff --git a/serializers/api/api_serializer.rb b/serializers/api/api_serializer.rb index 651e29fd..9d7fba70 100644 --- a/serializers/api/api_serializer.rb +++ b/serializers/api/api_serializer.rb @@ -2,7 +2,8 @@ class CustomWizard::ApiSerializer < ApplicationSerializer attributes :name, :title, :authorization, - :endpoints + :endpoints, + :log def authorization if authorization = CustomWizard::Api::Authorization.get(object.name) @@ -21,4 +22,13 @@ class CustomWizard::ApiSerializer < ApplicationSerializer ) end end + + def log + if log = CustomWizard::Api::LogEntry.list(object.name) + ActiveModel::ArraySerializer.new( + log, + each_serializer: CustomWizard::Api::LogSerializer + ) + end + end end diff --git a/serializers/api/log_serializer.rb b/serializers/api/log_serializer.rb new file mode 100644 index 00000000..754c15f3 --- /dev/null +++ b/serializers/api/log_serializer.rb @@ -0,0 +1,7 @@ +class CustomWizard::Api::LogSerializer < ApplicationSerializer + attributes :log_id, + :time, + :status, + :endpoint_url, + :error +end