Action logging and submissions bugixs
Dieser Commit ist enthalten in:
Ursprung
4c3e88beee
Commit
04198339ca
19 geänderte Dateien mit 193 neuen und 42 gelöschten Zeilen
|
@ -1,5 +1,5 @@
|
|||
import { default as discourseComputed, observes, on } from 'discourse-common/utils/decorators';
|
||||
import { equal, empty, or } from "@ember/object/computed";
|
||||
import { equal, empty, or, notEmpty } from "@ember/object/computed";
|
||||
import { generateName, selectKitContent, schema } from '../lib/wizard';
|
||||
import Component from "@ember/component";
|
||||
|
||||
|
@ -20,6 +20,7 @@ export default Component.extend({
|
|||
basicTopicFields: or('createTopic', 'sendMessage', 'openComposer'),
|
||||
publicTopicFields: or('createTopic', 'openComposer'),
|
||||
showSkipRedirect: or('createTopic', 'sendMessage'),
|
||||
showPostBuilder: notEmpty('action.post_template'),
|
||||
|
||||
@discourseComputed('wizard.steps')
|
||||
runAfterContent(steps) {
|
||||
|
|
52
assets/javascripts/discourse/controllers/admin-wizards-logs.js.es6
Normale Datei
52
assets/javascripts/discourse/controllers/admin-wizards-logs.js.es6
Normale Datei
|
@ -0,0 +1,52 @@
|
|||
import { default as computed } from 'discourse-common/utils/decorators';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { notEmpty } from "@ember/object/computed";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
refreshing: false,
|
||||
hasLogs: notEmpty("logs"),
|
||||
page: 0,
|
||||
canLoadMore: true,
|
||||
logs: [],
|
||||
|
||||
loadLogs() {
|
||||
if (!this.canLoadMore) return;
|
||||
|
||||
this.set("refreshing", true);
|
||||
|
||||
ajax('/admin/wizards/logs', {
|
||||
data: {
|
||||
page: this.page
|
||||
}
|
||||
}).catch(popupAjaxError)
|
||||
.then(result => {
|
||||
if (!result || result.length === 0) {
|
||||
this.set('canLoadMore', false);
|
||||
}
|
||||
this.set("logs", this.logs.concat(result));
|
||||
})
|
||||
.finally(() => this.set("refreshing", false));
|
||||
},
|
||||
|
||||
@computed('hasLogs', 'refreshing')
|
||||
noResults(hasLogs, refreshing) {
|
||||
return !hasLogs && !refreshing;
|
||||
},
|
||||
|
||||
actions: {
|
||||
loadMore() {
|
||||
this.set('page', this.page += 1);
|
||||
this.loadLogs();
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.setProperties({
|
||||
canLoadMore: true,
|
||||
page: 0,
|
||||
logs: []
|
||||
})
|
||||
this.loadLogs();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -15,6 +15,8 @@ export default {
|
|||
this.route('adminWizardsApiShow', { path: '/:name', resetNamespace: true });
|
||||
});
|
||||
|
||||
this.route('adminWizardsLogs', { path: '/logs', resetNamespace: true });
|
||||
|
||||
this.route('adminWizardsTransfer', { path: '/transfer', resetNamespace: true });
|
||||
});
|
||||
}
|
||||
|
|
28
assets/javascripts/discourse/templates/admin-wizards-logs.hbs
Normale Datei
28
assets/javascripts/discourse/templates/admin-wizards-logs.hbs
Normale Datei
|
@ -0,0 +1,28 @@
|
|||
<div class="admin-wizard-controls">
|
||||
{{d-button label="refresh" icon="refresh" action="refresh"}}
|
||||
</div>
|
||||
|
||||
{{#load-more selector=".log-list tr" action=(action "loadMore")}}
|
||||
{{#if noResults}}
|
||||
<p>{{i18n 'search.no_results'}}</p>
|
||||
{{else}}
|
||||
<table class="table grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Message</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each logs as |log|}}
|
||||
<tr>
|
||||
<td>{{log.message}}</td>
|
||||
<td>{{bound-date log.date}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
|
||||
{{conditional-loading-spinner condition=refreshing}}
|
||||
{{/load-more}}
|
|
@ -4,6 +4,7 @@
|
|||
{{#if siteSettings.wizard_api_features}}
|
||||
{{nav-item route='adminWizardsApis' label='admin.wizard.api.nav_label'}}
|
||||
{{/if}}
|
||||
{{nav-item route='adminWizardsLogs' label='admin.wizard.log.nav_label'}}
|
||||
{{nav-item route='adminWizardsTransfer' label='admin.wizard.transfer.nav_label'}}
|
||||
{{/admin-nav}}
|
||||
|
||||
|
|
|
@ -57,17 +57,17 @@
|
|||
onChange=(action (mut action.post))
|
||||
options=(hash
|
||||
none='admin.wizard.selector.placeholder.wizard_field'
|
||||
isDisabled=action.post_builder
|
||||
isDisabled=showPostBuilder
|
||||
)}}
|
||||
|
||||
<div class="setting-gutter">
|
||||
{{input type='checkbox' checked=action.post_builder}}
|
||||
{{input type='checkbox' checked=showPostBuilder}}
|
||||
<span>{{i18n 'admin.wizard.action.post_builder.checkbox'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if action.post_builder}}
|
||||
{{#if showPostBuilder}}
|
||||
<div class="setting full">
|
||||
<div class="setting-label">
|
||||
<label>{{i18n 'admin.wizard.action.post_builder.label'}}</label>
|
||||
|
|
|
@ -54,9 +54,9 @@
|
|||
{{#if showTag}}
|
||||
{{tag-chooser
|
||||
tags=value
|
||||
filterable=true
|
||||
options=(hash
|
||||
none=placeholderKey
|
||||
filterable=true
|
||||
)}}
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -24,12 +24,10 @@
|
|||
|
||||
.admin-wizard-container {
|
||||
margin-top: 20px;
|
||||
|
||||
.row > .content table {
|
||||
margin-top: 0;
|
||||
min-width: 100%;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.wizard-submissions {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.wizard-settings-parent {
|
||||
|
|
|
@ -261,6 +261,9 @@ en:
|
|||
log:
|
||||
label: "Logs"
|
||||
|
||||
log:
|
||||
nav_label: "Logs"
|
||||
|
||||
transfer:
|
||||
nav_label: "Transfer"
|
||||
export:
|
||||
|
|
|
@ -31,4 +31,3 @@ en:
|
|||
wizard_recognised_image_upload_formats: "File types which will result in upload displaying an image preview"
|
||||
wizard_step_advanced: "Enable advanced settings for wizard steps (experimental)."
|
||||
wizard_api_features: "Enable API features (experimental)."
|
||||
wizard_action_debug: "Log action details for debugging."
|
|
@ -32,6 +32,8 @@ Discourse::Application.routes.append do
|
|||
get 'admin/wizards/apis/:name/redirect' => 'admin_api#redirect'
|
||||
get 'admin/wizards/apis/:name/authorize' => 'admin_api#authorize'
|
||||
|
||||
get 'admin/wizards/logs' => 'admin_logs#index'
|
||||
|
||||
get 'admin/wizards/transfer' => 'transfer#index'
|
||||
get 'admin/wizards/transfer/export' => 'transfer#export'
|
||||
post 'admin/wizards/transfer/import' => 'transfer#import'
|
||||
|
|
|
@ -21,5 +21,3 @@ plugins:
|
|||
wizard_api_features:
|
||||
client: true
|
||||
default: false
|
||||
wizard_action_debug:
|
||||
default: false
|
8
controllers/custom_wizard/admin/logs.rb
Normale Datei
8
controllers/custom_wizard/admin/logs.rb
Normale Datei
|
@ -0,0 +1,8 @@
|
|||
class CustomWizard::AdminLogsController < CustomWizard::AdminController
|
||||
def index
|
||||
render_serialized(
|
||||
CustomWizard::Log.list(params[:page].to_i),
|
||||
CustomWizard::LogSerializer
|
||||
)
|
||||
end
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
||||
skip_before_action :check_xhr, only: [:download_submissions]
|
||||
skip_before_action :preload_json, :check_xhr, only: [:download]
|
||||
|
||||
before_action :find_wizard
|
||||
|
||||
def index
|
||||
|
@ -23,8 +24,9 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
|||
|
||||
def download
|
||||
send_data build_submissions(@wizard.id).to_json,
|
||||
filename: "#{Discourse.current_hostname}-wizard-submissions-#{wizard['name']}.json",
|
||||
content_type: "application/json"
|
||||
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
||||
content_type: "application/json",
|
||||
disposition: "attachment"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -6,27 +6,29 @@ class CustomWizard::Action
|
|||
:result
|
||||
|
||||
def initialize(params)
|
||||
@wizard = params[:wizard]
|
||||
@action = params[:action]
|
||||
@user = params[:user]
|
||||
@data = params[:data]
|
||||
@updater = params[:updater]
|
||||
@log = []
|
||||
end
|
||||
|
||||
def perform
|
||||
ActiveRecord::Base.transaction do
|
||||
self.send(action['type'].to_sym)
|
||||
|
||||
if SiteSetting.wizard_action_debug
|
||||
log = "action: #{action['type']}; "
|
||||
log << "result: #{@result}"
|
||||
|
||||
updater.errors.messages.each do |field, msg|
|
||||
log << "error: #{field.to_s}; #{msg.to_s}; "
|
||||
end
|
||||
|
||||
Rails.logger.warn("Wizard Action: #{log.to_s}")
|
||||
log = "wizard: #{@wizard.id}; action: #{action['type']}; user: #{user.username}"
|
||||
|
||||
if @log.any?
|
||||
@log.each do |item|
|
||||
log << "; result: "
|
||||
log << item.to_s
|
||||
end
|
||||
end
|
||||
|
||||
CustomWizard::Log.create(log)
|
||||
end
|
||||
|
||||
def mapper
|
||||
|
@ -44,17 +46,18 @@ class CustomWizard::Action
|
|||
post = creator.create
|
||||
|
||||
if creator.errors.present?
|
||||
@result = "failed to create"
|
||||
updater.errors.add(:create_topic, creator.errors.full_messages.join(" "))
|
||||
messages = creator.errors.full_messages.join(" ")
|
||||
log_error("failed to create", messages)
|
||||
updater.errors.add(:create_topic, messages)
|
||||
elsif action['skip_redirect'].blank?
|
||||
data['redirect_on_complete'] = post.topic.url
|
||||
end
|
||||
|
||||
if creator.errors.blank?
|
||||
@result = "success (created topic: #{post.topic.id})"
|
||||
log_success("created topic", post.topic.id)
|
||||
end
|
||||
else
|
||||
@result = "invalid params"
|
||||
log_error("invalid topic params")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,17 +78,18 @@ class CustomWizard::Action
|
|||
post = creator.create
|
||||
|
||||
if creator.errors.present?
|
||||
@result = "failed to create"
|
||||
updater.errors.add(:send_message, creator.errors.full_messages.join(" "))
|
||||
messages = creator.errors.full_messages.join(" ")
|
||||
log_error("failed to create message", messages)
|
||||
updater.errors.add(:send_message, messages)
|
||||
elsif action['skip_redirect'].blank?
|
||||
data['redirect_on_complete'] = post.topic.url
|
||||
end
|
||||
|
||||
if creator.errors.blank?
|
||||
@result = "success (created pm: #{post.topic.id})"
|
||||
log_error("created message", post.topic.id)
|
||||
end
|
||||
else
|
||||
@result = "invalid params"
|
||||
log_error("invalid message params")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -111,12 +115,12 @@ class CustomWizard::Action
|
|||
end
|
||||
|
||||
if result
|
||||
@result = "success (updated fields #{params.keys.map{ |p| p.to_s }.join(',')})"
|
||||
log_success("updated profile fields", params.keys.map{ |p| p.to_s }.join(','))
|
||||
else
|
||||
@result = "failed to update"
|
||||
log_error("failed to update profile fields")
|
||||
end
|
||||
else
|
||||
@result = "invalid params"
|
||||
log_error("invalid profile fields params")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -201,9 +205,9 @@ class CustomWizard::Action
|
|||
end
|
||||
|
||||
if result
|
||||
@result = "success (added to groups: #{groups.map { |g| g.id.to_s }.join(',')})"
|
||||
log_success("added to groups", groups.map { |g| g.id.to_s }.join(','))
|
||||
else
|
||||
@result = "failed to add"
|
||||
log_error("failed to add to groups")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -333,4 +337,12 @@ class CustomWizard::Action
|
|||
user.save!
|
||||
user.user_avatar.save!
|
||||
end
|
||||
|
||||
def log_success(message, detail = nil)
|
||||
@log.push("success - #{message} - #{detail}")
|
||||
end
|
||||
|
||||
def log_error(message, detail = nil)
|
||||
@log.push("error - #{message} - #{detail}")
|
||||
end
|
||||
end
|
|
@ -157,6 +157,7 @@ class CustomWizard::Builder
|
|||
(final_step && (!action['run_after'] || (action['run_after'] === 'wizard_completion')))
|
||||
|
||||
CustomWizard::Action.new(
|
||||
wizard: @wizard,
|
||||
action: action,
|
||||
user: user,
|
||||
data: data,
|
||||
|
|
38
lib/custom_wizard/log.rb
Normale Datei
38
lib/custom_wizard/log.rb
Normale Datei
|
@ -0,0 +1,38 @@
|
|||
class CustomWizard::Log
|
||||
include ActiveModel::Serialization
|
||||
|
||||
attr_accessor :message, :date
|
||||
|
||||
PAGE_LIMIT = 100
|
||||
|
||||
def initialize(attrs)
|
||||
@message = attrs['message']
|
||||
@date = attrs['date']
|
||||
end
|
||||
|
||||
def self.create(message)
|
||||
log_id = SecureRandom.hex(12)
|
||||
|
||||
PluginStore.set('custom_wizard',
|
||||
"log_#{log_id}",
|
||||
{
|
||||
date: Time.now,
|
||||
message: message
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def self.list_query
|
||||
PluginStoreRow.where("
|
||||
plugin_name = 'custom_wizard' AND
|
||||
key LIKE 'log_%' AND
|
||||
(value::json->'date') IS NOT NULL
|
||||
").order("value::json->>'date' DESC")
|
||||
end
|
||||
|
||||
def self.list(page = 0)
|
||||
self.list_query.limit(PAGE_LIMIT)
|
||||
.offset(page * PAGE_LIMIT)
|
||||
.map { |r| self.new(JSON.parse(r.value)) }
|
||||
end
|
||||
end
|
|
@ -48,6 +48,7 @@ after_initialize do
|
|||
../controllers/custom_wizard/admin/wizard.rb
|
||||
../controllers/custom_wizard/admin/submissions.rb
|
||||
../controllers/custom_wizard/admin/api.rb
|
||||
../controllers/custom_wizard/admin/logs.rb
|
||||
../controllers/custom_wizard/wizard.rb
|
||||
../controllers/custom_wizard/steps.rb
|
||||
../controllers/custom_wizard/transfer.rb
|
||||
|
@ -57,10 +58,11 @@ after_initialize do
|
|||
../jobs/clear_after_time_wizard.rb
|
||||
../jobs/refresh_api_access_token.rb
|
||||
../jobs/set_after_time_wizard.rb
|
||||
../lib/custom_wizard/actions.rb
|
||||
../lib/custom_wizard/action.rb
|
||||
../lib/custom_wizard/builder.rb
|
||||
../lib/custom_wizard/field.rb
|
||||
../lib/custom_wizard/mapper.rb
|
||||
../lib/custom_wizard/log.rb
|
||||
../lib/custom_wizard/step_updater.rb
|
||||
../lib/custom_wizard/validator.rb
|
||||
../lib/custom_wizard/wizard.rb
|
||||
|
@ -80,6 +82,7 @@ after_initialize do
|
|||
../serializers/custom_wizard/wizard_field_serializer.rb
|
||||
../serializers/custom_wizard/wizard_step_serializer.rb
|
||||
../serializers/custom_wizard/wizard_serializer.rb
|
||||
../serializers/custom_wizard/log_serializer.rb
|
||||
../serializers/site_serializer.rb
|
||||
].each do |path|
|
||||
load File.expand_path(path, __FILE__)
|
||||
|
|
3
serializers/custom_wizard/log_serializer.rb
Normale Datei
3
serializers/custom_wizard/log_serializer.rb
Normale Datei
|
@ -0,0 +1,3 @@
|
|||
class CustomWizard::LogSerializer < ApplicationSerializer
|
||||
attributes :message, :date
|
||||
end
|
Laden …
In neuem Issue referenzieren