1
0
Fork 0
discourse-custom-wizard-unl.../lib/custom_wizard/action.rb

367 Zeilen
9 KiB
Ruby

2020-03-30 08:16:03 +02:00
class CustomWizard::Action
attr_accessor :data,
:action,
:user,
2020-04-14 16:10:26 +02:00
:updater,
:result
2020-03-30 08:16:03 +02:00
def initialize(params)
2020-04-15 02:46:44 +02:00
@wizard = params[:wizard]
2020-03-30 08:16:03 +02:00
@action = params[:action]
@user = params[:user]
@data = params[:data]
@updater = params[:updater]
2020-04-15 02:46:44 +02:00
@log = []
2020-03-30 08:16:03 +02:00
end
def perform
2020-04-14 16:10:26 +02:00
ActiveRecord::Base.transaction do
self.send(action['type'].to_sym)
2020-04-15 02:46:44 +02:00
end
log = "wizard: #{@wizard.id}; action: #{action['type']}; user: #{user.username}"
if @log.any?
@log.each do |item|
log << "; result: "
log << item.to_s
2020-04-14 16:10:26 +02:00
end
end
2020-04-15 02:46:44 +02:00
CustomWizard::Log.create(log)
2020-03-30 08:16:03 +02:00
end
def mapper
@mapper ||= CustomWizard::Mapper.new(user: user, data: data)
end
2020-03-31 08:29:59 +02:00
def create_topic
2020-04-02 07:21:57 +02:00
params = basic_topic_params
2020-04-14 16:10:26 +02:00
if params[:title].present? && params[:raw].present?
2020-04-02 07:21:57 +02:00
params[:category] = action_category
params[:tags] = action_tags
2020-03-30 08:16:03 +02:00
creator = PostCreator.new(user, params)
post = creator.create
2020-04-14 16:10:26 +02:00
2020-03-30 08:16:03 +02:00
if creator.errors.present?
2020-04-15 02:46:44 +02:00
messages = creator.errors.full_messages.join(" ")
log_error("failed to create", messages)
updater.errors.add(:create_topic, messages)
2020-04-02 07:21:57 +02:00
elsif action['skip_redirect'].blank?
data['redirect_on_complete'] = post.topic.url
2020-03-30 08:16:03 +02:00
end
2020-04-14 16:10:26 +02:00
if creator.errors.blank?
2020-04-15 03:06:50 +02:00
log_success("created topic", "id: #{post.topic.id}")
2020-04-14 16:10:26 +02:00
end
else
2020-04-15 03:05:26 +02:00
log_error("invalid topic params", "title: #{params[:title]}; post: #{params[:raw]}")
2020-03-30 08:16:03 +02:00
end
end
def send_message
2020-04-15 03:05:26 +02:00
if action['required'].present? && data[action['required']].blank?
log_error(
"required not present",
"required: #{action['required']}; data: #{data[action['required']]}"
)
return
end
2020-03-30 08:16:03 +02:00
2020-04-02 07:21:57 +02:00
params = basic_topic_params
params[:target_usernames] = CustomWizard::Mapper.new(
inputs: action['recipient'],
data: data,
2020-04-02 10:21:03 +02:00
user: user
2020-04-06 10:36:38 +02:00
).perform
2020-04-02 10:21:03 +02:00
if params[:title].present? && params[:raw].present? && params[:target_usernames].present?
2020-04-02 07:21:57 +02:00
params[:archetype] = Archetype.private_message
creator = PostCreator.new(user, params)
2020-03-30 08:16:03 +02:00
post = creator.create
if creator.errors.present?
2020-04-15 02:46:44 +02:00
messages = creator.errors.full_messages.join(" ")
log_error("failed to create message", messages)
updater.errors.add(:send_message, messages)
2020-04-02 07:21:57 +02:00
elsif action['skip_redirect'].blank?
data['redirect_on_complete'] = post.topic.url
2020-03-30 08:16:03 +02:00
end
2020-04-14 16:10:26 +02:00
if creator.errors.blank?
2020-04-15 03:06:50 +02:00
log_error("created message", "id: #{post.topic.id}")
2020-04-14 16:10:26 +02:00
end
else
2020-04-15 03:05:26 +02:00
log_error(
"invalid message params",
"title: #{params[:title]}; post: #{params[:raw]}; recipients: #{params[:target_usernames]}"
)
2020-03-30 08:16:03 +02:00
end
end
def update_profile
2020-04-02 07:21:57 +02:00
return unless (profile_updates = action['profile_updates']).length
2020-04-07 15:33:11 +02:00
params = {}
profile_updates.first[:pairs].each do |pair|
2020-04-07 16:18:12 +02:00
if allowed_profile_fields.include?(pair['key'])
key = cast_profile_key(pair['key']).to_sym
value = mapper.map_field(pair['value'], pair['value_type'])
params[key] = cast_profile_value(value, pair['key'])
2020-03-30 08:16:03 +02:00
end
end
2020-04-07 15:33:11 +02:00
params = add_custom_fields(params)
if params.present?
2020-04-14 16:10:26 +02:00
result = UserUpdater.new(Discourse.system_user, user).update(params)
2020-04-07 15:33:11 +02:00
if params[:avatar].present?
2020-04-14 16:10:26 +02:00
result = update_avatar(params[:avatar])
end
if result
2020-04-15 02:46:44 +02:00
log_success("updated profile fields", params.keys.map{ |p| p.to_s }.join(','))
2020-04-14 16:10:26 +02:00
else
2020-04-15 02:46:44 +02:00
log_error("failed to update profile fields")
2020-04-07 15:33:11 +02:00
end
2020-04-14 16:10:26 +02:00
else
2020-04-15 03:05:26 +02:00
log_error("invalid profile fields params", params.inspect)
2020-03-30 08:16:03 +02:00
end
end
def send_to_api
api_body = nil
if action['api_body'] != ""
begin
api_body_parsed = JSON.parse(action['api_body'])
rescue JSON::ParserError
raise Discourse::InvalidParameters, "Invalid API body definition: #{action['api_body']} for #{action['title']}"
end
api_body = JSON.parse(mapper.interpolate(JSON.generate(api_body_parsed)))
end
result = CustomWizard::Api::Endpoint.request(user, action['api'], action['api_endpoint'], api_body)
if error = result['error'] || (result[0] && result[0]['error'])
error = error['message'] || error
updater.errors.add(:send_to_api, error)
else
## add validation callback
end
end
def open_composer
2020-03-30 08:16:03 +02:00
if action['custom_title_enabled']
title = mapper.interpolate(action['custom_title'])
else
title = data[action['title']]
end
url = "/new-topic?title=#{title}"
if action['post_builder']
post = mapper.interpolate(action['post_template'])
else
post = data[action['post']]
end
url += "&body=#{post}"
2020-04-02 07:21:57 +02:00
if category_id = action_category
2020-03-30 08:16:03 +02:00
if category = Category.find(category_id)
url += "&category=#{category.full_slug('/')}"
end
end
2020-03-31 08:29:59 +02:00
if tags = action_tags
2020-03-30 08:16:03 +02:00
url += "&tags=#{tags.join(',')}"
end
2020-04-15 03:05:26 +02:00
route_to = Discourse.base_uri + URI.encode(url)
data['redirect_on_complete'] = route_to
log_info("route: #{route_to}")
2020-03-30 08:16:03 +02:00
end
def add_to_group
groups = CustomWizard::Mapper.new(
inputs: action['group'],
2020-03-30 08:16:03 +02:00
data: data,
user: user,
opts: {
multiple: true
}
2020-04-06 10:36:38 +02:00
).perform
2020-03-30 08:16:03 +02:00
groups = groups.flatten.reduce([]) do |result, g|
begin
result.push(Integer(g))
rescue ArgumentError
group = Group.find_by(name: g)
result.push(group.id) if group
end
result
end
if groups.present?
groups.each do |group_id|
group = Group.find(group_id) if group_id
2020-04-14 16:10:26 +02:00
result = group.add(user) if group
2020-03-30 08:16:03 +02:00
end
end
2020-04-14 16:10:26 +02:00
if result
2020-04-15 02:46:44 +02:00
log_success("added to groups", groups.map { |g| g.id.to_s }.join(','))
2020-04-14 16:10:26 +02:00
else
2020-04-15 02:46:44 +02:00
log_error("failed to add to groups")
2020-04-14 16:10:26 +02:00
end
2020-03-30 08:16:03 +02:00
end
def route_to
url = mapper.interpolate(action['url'])
2020-03-30 08:16:03 +02:00
if action['code']
data[action['code']] = SecureRandom.hex(8)
url += "&#{action['code']}=#{data[action['code']]}"
end
2020-04-02 07:21:57 +02:00
2020-04-15 03:05:26 +02:00
route_to = URI.encode(url)
data['route_to'] = route_to
log_info("route: #{route_to}")
2020-03-30 08:16:03 +02:00
end
2020-04-02 07:21:57 +02:00
private
def action_category
output = CustomWizard::Mapper.new(
inputs: action['category'],
data: data,
user: user
2020-04-06 10:36:38 +02:00
).perform
2020-04-02 07:21:57 +02:00
if output.is_a?(Array)
output.first
elsif output.is_a?(Integer)
output
elsif output.is_a?(String)
output.to_i
2020-03-30 08:16:03 +02:00
end
end
def action_tags
2020-04-02 07:21:57 +02:00
output = CustomWizard::Mapper.new(
inputs: action['tags'],
data: data,
user: user,
2020-04-06 10:36:38 +02:00
).perform
2020-04-07 13:17:20 +02:00
2020-04-02 07:21:57 +02:00
if output.is_a?(Array)
output.flatten
2020-04-07 13:17:20 +02:00
else output.is_a?(String)
2020-04-02 07:21:57 +02:00
[*output]
end
end
def add_custom_fields(params = {})
if (custom_fields = action['custom_fields']).present?
2020-04-06 10:36:38 +02:00
field_map = CustomWizard::Mapper.new(
inputs: custom_fields,
data: data,
user: user
).perform
field_map.each do |field|
keyArr = field[:key].split('.')
value = field[:value]
2020-04-02 07:21:57 +02:00
2020-04-07 15:33:11 +02:00
if keyArr.first === 'topic'
2020-04-06 10:36:38 +02:00
params[:topic_opts] ||= {}
params[:topic_opts][:custom_fields] ||= {}
params[:topic_opts][:custom_fields][keyArr.last] = value
2020-04-07 15:33:11 +02:00
else
2020-04-06 10:36:38 +02:00
params[:custom_fields] ||= {}
params[:custom_fields][keyArr.last.to_sym] = value
2020-04-02 07:21:57 +02:00
end
end
2020-03-30 08:16:03 +02:00
end
2020-04-02 07:21:57 +02:00
params
end
def basic_topic_params
params = {
skip_validations: true
}
params[:title] = CustomWizard::Mapper.new(
inputs: action['title'],
data: data,
user: user
2020-04-06 10:36:38 +02:00
).perform
2020-04-02 07:21:57 +02:00
2020-04-15 03:13:06 +02:00
params[:raw] = action['post_template'] ?
2020-04-02 07:21:57 +02:00
mapper.interpolate(action['post_template']) :
data[action['post']]
2020-04-07 15:33:11 +02:00
add_custom_fields(params)
2020-03-30 08:16:03 +02:00
end
2020-04-07 16:18:12 +02:00
def profile_url_fields
['profile_background', 'card_background']
end
def cast_profile_key(key)
if profile_url_fields.include?(key)
"#{key}_upload_url"
else
key
end
end
def cast_profile_value(value, key)
if profile_url_fields.include?(key)
value['url']
elsif key === 'avatar'
value['id']
else
value
end
end
2020-04-10 10:51:01 +02:00
def profile_excluded_fields
['username', 'email', 'trust_level'].freeze
2020-04-10 10:51:01 +02:00
end
2020-04-07 16:18:12 +02:00
def allowed_profile_fields
2020-04-10 10:51:01 +02:00
CustomWizard::Mapper.user_fields.select { |f| profile_excluded_fields.exclude?(f) } +
2020-04-07 16:18:12 +02:00
profile_url_fields +
['avatar']
end
def update_avatar(upload_id)
user.create_user_avatar unless user.user_avatar
user.user_avatar.custom_upload_id = upload_id
user.uploaded_avatar_id = upload_id
user.save!
user.user_avatar.save!
end
2020-04-15 02:46:44 +02:00
def log_success(message, detail = nil)
@log.push("success - #{message} - #{detail}")
end
def log_error(message, detail = nil)
@log.push("error - #{message} - #{detail}")
end
2020-04-15 03:05:26 +02:00
def log_info(mesage, detail = nil)
@log.push("info - #{message} - #{detail}")
end
2020-03-30 08:16:03 +02:00
end