Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion config/locales/server.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ en:
validation:
required: "%{property} is required"
conflict: "Wizard with id '%{wizard_id}' already exists"
after_time: "After time setting is invalid"
after_signup: "You can only have one 'after signup' wizard at a time. %{wizard_id} has 'after signup' enabled."
after_signup_after_time: "You can't use 'after time' and 'after signup' on the same wizard."
after_time: "After time setting is invalid."

site_settings:
custom_wizard_enabled: "Enable custom wizards."
Expand Down
2 changes: 1 addition & 1 deletion controllers/custom_wizard/steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def update
updater.result[:redirect_on_complete] = redirect
end

@wizard.final_cleanup!
@wizard.cleanup_on_complete!

result[:final] = true
else
Expand Down
12 changes: 4 additions & 8 deletions controllers/custom_wizard/wizard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,13 @@ def skip
end

result = success_json
user = current_user

if user && wizard.can_access?
submission = wizard.current_submission

if submission.present? && submission.redirect_to
result.merge!(redirect_to: submission.redirect_to)
if current_user && wizard.can_access?
if redirect_to = wizard.current_submission&.redirect_to
result.merge!(redirect_to: redirect_to)
end

submission.remove if submission.present?
wizard.reset
wizard.cleanup_on_skip!
end

render json: result
Expand Down
2 changes: 1 addition & 1 deletion coverage/.last_run.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"result": {
"line": 91.83
"line": 92.52
}
}
2 changes: 1 addition & 1 deletion extensions/invites_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
module InvitesControllerCustomWizard
def path(url)
if ::Wizard.user_requires_completion?(@user)
wizard_id = @user.custom_fields['redirect_to_wizard']
wizard_id = @user.redirect_to_wizard

if wizard_id && url != '/'
CustomWizard::Wizard.set_wizard_redirect(@user, wizard_id, url)
Expand Down
2 changes: 2 additions & 0 deletions jobs/set_after_time_wizard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def execute(args)
end
end

CustomWizard::Template.clear_cache_keys

MessageBus.publish "/redirect_to_wizard", wizard.id, user_ids: user_ids
end
end
Expand Down
47 changes: 40 additions & 7 deletions lib/custom_wizard/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
class CustomWizard::Template
include HasErrors

AFTER_SIGNUP_CACHE_KEY ||= "after_signup_wizard_ids"
AFTER_TIME_CACHE_KEY ||= "after_time_wizard_ids"

attr_reader :data,
:opts,
:steps,
Expand All @@ -28,6 +31,8 @@ def save(opts = {})
PluginStore.set(CustomWizard::PLUGIN_NAME, @data[:id], @data)
end

self.class.clear_cache_keys

@data[:id]
end

Expand All @@ -53,10 +58,10 @@ def self.remove(wizard_id)

ActiveRecord::Base.transaction do
PluginStore.remove(CustomWizard::PLUGIN_NAME, wizard.id)
clear_user_wizard_redirect(wizard_id)
clear_user_wizard_redirect(wizard_id, after_time: !!wizard.after_time)
end

Jobs.cancel_scheduled_job(:set_after_time_wizard) if wizard.after_time
clear_cache_keys

true
end
Expand All @@ -65,9 +70,10 @@ def self.exists?(wizard_id)
PluginStoreRow.exists?(plugin_name: 'custom_wizard', key: wizard_id)
end

def self.list(setting: nil, order: :id)
def self.list(setting: nil, query_str: nil, order: :id)
query = "plugin_name = 'custom_wizard'"
query += "AND (value::json ->> '#{setting}')::boolean IS TRUE" if setting
query += " AND (value::json ->> '#{setting}')::boolean IS TRUE" if setting
query += " #{query_str}" if query_str

PluginStoreRow.where(query).order(order)
.reduce([]) do |result, record|
Expand All @@ -85,8 +91,36 @@ def self.list(setting: nil, order: :id)
end
end

def self.clear_user_wizard_redirect(wizard_id)
def self.clear_user_wizard_redirect(wizard_id, after_time: false)
UserCustomField.where(name: 'redirect_to_wizard', value: wizard_id).destroy_all

if after_time
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard_id)
end
end

def self.after_signup_ids
::CustomWizard::Cache.wrap(AFTER_SIGNUP_CACHE_KEY) do
list(setting: 'after_signup').map { |t| t['id'] }
end
end

def self.after_time_ids
::CustomWizard::Cache.wrap(AFTER_TIME_CACHE_KEY) do
list(
setting: 'after_time',
query_str: "AND (value::json ->> 'after_time_scheduled')::timestamp < CURRENT_TIMESTAMP"
).map { |t| t['id'] }
end
end

def self.can_redirect_users?(wizard_id)
after_signup_ids.include?(wizard_id) || after_time_ids.include?(wizard_id)
end

def self.clear_cache_keys
CustomWizard::Cache.new(AFTER_SIGNUP_CACHE_KEY).delete
CustomWizard::Cache.new(AFTER_TIME_CACHE_KEY).delete
end

private
Expand Down Expand Up @@ -132,8 +166,7 @@ def schedule_save_jobs
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard_id)
Jobs.enqueue_at(enqueue_wizard_at, :set_after_time_wizard, wizard_id: wizard_id)
elsif old_data && old_data[:after_time]
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard_id)
self.class.clear_user_wizard_redirect(wizard_id)
clear_user_wizard_redirect(wizard_id, after_time: true)
end
end
end
Expand Down
27 changes: 21 additions & 6 deletions lib/custom_wizard/validators/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ def perform

check_id(data, :wizard)
check_required(data, :wizard)
validate_after_signup
validate_after_time

return false if errors.any?

data[:steps].each do |step|
check_required(step, :step)

Expand All @@ -31,11 +34,7 @@ def perform
end
end

if errors.any?
false
else
true
end
!errors.any?
end

def self.required
Expand Down Expand Up @@ -63,8 +62,24 @@ def check_id(object, type)
end
end

def validate_after_signup
return unless ActiveRecord::Type::Boolean.new.cast(@data[:after_signup])

other_after_signup = CustomWizard::Template.list(setting: 'after_signup')
.select { |template| template['id'] != @data[:id] }

if other_after_signup.any?
errors.add :base, I18n.t("wizard.validation.after_signup", wizard_id: other_after_signup.first['id'])
end
end

def validate_after_time
return unless @data[:after_time]
return unless ActiveRecord::Type::Boolean.new.cast(@data[:after_time])

if ActiveRecord::Type::Boolean.new.cast(@data[:after_signup])
errors.add :base, I18n.t("wizard.validation.after_signup_after_time")
return
end

wizard = CustomWizard::Wizard.create(@data[:id]) if !@opts[:create]
current_time = wizard.present? ? wizard.after_time_scheduled : nil
Expand Down
24 changes: 19 additions & 5 deletions lib/custom_wizard/wizard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,8 @@ def current_submission
end
end

def final_cleanup!
if id == user.custom_fields['redirect_to_wizard']
user.custom_fields.delete('redirect_to_wizard')
user.save_custom_fields(true)
end
def cleanup_on_complete!
remove_user_redirect

if current_submission.present?
current_submission.submitted_at = Time.now.iso8601
Expand All @@ -302,6 +299,23 @@ def final_cleanup!
update!
end

def cleanup_on_skip!
remove_user_redirect

if current_submission.present?
current_submission.remove
end

reset
end

def remove_user_redirect
if id == user.redirect_to_wizard
user.custom_fields.delete('redirect_to_wizard')
user.save_custom_fields(true)
end
end

def self.create(wizard_id, user = nil)
if template = CustomWizard::Template.find(wizard_id)
new(template.to_h, user)
Expand Down
30 changes: 21 additions & 9 deletions plugin.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# name: discourse-custom-wizard
# about: Create custom wizards
# version: 1.16.4
# version: 1.16.5
# authors: Angus McLeod
# url: https://github.com/paviliondev/discourse-custom-wizard
# contact emails: angus@thepavilion.io
Expand Down Expand Up @@ -149,16 +149,24 @@ def process_require_tree_discourse_directive(path = ".")
!!custom_redirect
end

add_to_class(:user, :redirect_to_wizard) do
if custom_fields['redirect_to_wizard'].present?
custom_fields['redirect_to_wizard']
else
nil
end
end

add_to_class(:users_controller, :wizard_path) do
if custom_wizard_redirect = current_user.custom_fields['redirect_to_wizard']
if custom_wizard_redirect = current_user.redirect_to_wizard
"#{Discourse.base_url}/w/#{custom_wizard_redirect.dasherize}"
else
"#{Discourse.base_url}/wizard"
end
end

add_to_serializer(:current_user, :redirect_to_wizard) do
object.custom_fields['redirect_to_wizard']
object.redirect_to_wizard
end

on(:user_approved) do |user|
Expand All @@ -168,15 +176,19 @@ def process_require_tree_discourse_directive(path = ".")
end

add_to_class(:application_controller, :redirect_to_wizard_if_required) do
wizard_id = current_user.custom_fields['redirect_to_wizard']
@excluded_routes ||= SiteSetting.wizard_redirect_exclude_paths.split('|') + ['/w/']
url = request.referer || request.original_url
excluded_route = @excluded_routes.any? { |str| /#{str}/ =~ url }
not_api = request.format === 'text/html'

if not_api && !excluded_route
wizard_id = current_user.redirect_to_wizard

if CustomWizard::Template.can_redirect_users?(wizard_id)
if url !~ /\/w\// && url !~ /\/invites\//
CustomWizard::Wizard.set_wizard_redirect(current_user, wizard_id, url)
end

if request.format === 'text/html' && !@excluded_routes.any? { |str| /#{str}/ =~ url } && wizard_id
if request.referer !~ /\/w\// && request.referer !~ /\/invites\//
CustomWizard::Wizard.set_wizard_redirect(current_user, wizard_id, request.referer)
end
if CustomWizard::Template.exists?(wizard_id)
redirect_to "/w/#{wizard_id.dasherize}"
end
end
Expand Down
32 changes: 32 additions & 0 deletions spec/components/custom_wizard/template_validator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,38 @@
).to eq(false)
end

it "only allows one after signup wizard at a time" do
wizard_id = template[:id]
template[:after_signup] = true
CustomWizard::Template.save(template)

template[:id] = "wizard_2"
template[:after_signup] = true

validator = CustomWizard::TemplateValidator.new(template)
expect(validator.perform).to eq(false)
expect(validator.errors.first.type).to eq(
I18n.t("wizard.validation.after_signup", wizard_id: wizard_id)
)
end

it "only allows a wizard with after signup to be validated twice" do
template[:after_signup] = true
CustomWizard::Template.save(template)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end

it "only allows one after _ setting per wizard" do
template[:after_signup] = true
template[:after_time] = true

validator = CustomWizard::TemplateValidator.new(template)
expect(validator.perform).to eq(false)
expect(validator.errors.first.type).to eq(
I18n.t("wizard.validation.after_signup_after_time")
)
end

it "validates after time settings" do
template[:after_time] = true
template[:after_time_scheduled] = (Time.now + 3.hours).iso8601
Expand Down
3 changes: 0 additions & 3 deletions spec/requests/custom_wizard/admin/manager_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@

template_2 = template.dup
template_2["id"] = 'super_mega_fun_wizard_2'

template_3 = template.dup
template_3["id"] = 'super_mega_fun_wizard_3'
template_3["after_signup"] = true

@template_array = [template, template_2, template_3]

FileUtils.mkdir_p(file_from_fixtures_tmp_folder) unless Dir.exists?(file_from_fixtures_tmp_folder)
Expand Down
Loading