From d9d4c7d8fa0788057cbce76efda1318bce0b8d44 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Thu, 14 Oct 2021 18:27:18 +0530 Subject: [PATCH 1/6] WIP --- lib/custom_wizard/guardian.rb | 33 +++++++++++++++++++ plugin.rb | 1 + .../components/custom_wizard/guardian_spec.rb | 6 ++++ 3 files changed, 40 insertions(+) create mode 100644 lib/custom_wizard/guardian.rb create mode 100644 spec/components/custom_wizard/guardian_spec.rb diff --git a/lib/custom_wizard/guardian.rb b/lib/custom_wizard/guardian.rb new file mode 100644 index 00000000..c453f509 --- /dev/null +++ b/lib/custom_wizard/guardian.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +class CustomWizard::Guardian + def initialize(user) + @user = user + end + + def can_edit_topic?(topic) + creating_wizard = topic.wizard_created.presence + return false unless creating_wizard + + wizard_builder = CustomWizard::Builder.new(creating_wizard, @user) + wizard = wizard_builder.build + wizard_actions = wizard.actions + return false if wizard_actions.empty? + + create_topic_action = wizard_actions.find do |action| + action['type'] === 'create_topic' + end + + return wizard_can_create_topic_on_category?(action, topic) + end + + private + + def wizard_can_create_topic_on_category?(action, topic) + return false unless topic.category.present? + + category = CustomWizard::Mapper.new( + inputs: action['category'], + data: + ) + end +end diff --git a/plugin.rb b/plugin.rb index 7e8c50e9..d412c76b 100644 --- a/plugin.rb +++ b/plugin.rb @@ -86,6 +86,7 @@ after_initialize do ../lib/custom_wizard/submission.rb ../lib/custom_wizard/template.rb ../lib/custom_wizard/wizard.rb + ../lib/custom_wizard/guardian.rb ../lib/custom_wizard/api/api.rb ../lib/custom_wizard/api/authorization.rb ../lib/custom_wizard/api/endpoint.rb diff --git a/spec/components/custom_wizard/guardian_spec.rb b/spec/components/custom_wizard/guardian_spec.rb new file mode 100644 index 00000000..bb7578d2 --- /dev/null +++ b/spec/components/custom_wizard/guardian_spec.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +require_relative '../../plugin_helper' + +describe CustomWizard::Guardian do + +end From 687c3530b388ba1c87cad3447b6ef7d909097478 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Tue, 19 Oct 2021 09:05:55 +0530 Subject: [PATCH 2/6] WIP --- extensions/guardian.rb | 59 ++++++++++++++++ lib/custom_wizard/action.rb | 8 ++- lib/custom_wizard/guardian.rb | 33 --------- plugin.rb | 11 ++- .../components/custom_wizard/guardian_spec.rb | 6 -- spec/extensions/guardian_extension_spec.rb | 68 +++++++++++++++++++ 6 files changed, 144 insertions(+), 41 deletions(-) create mode 100644 extensions/guardian.rb delete mode 100644 lib/custom_wizard/guardian.rb delete mode 100644 spec/components/custom_wizard/guardian_spec.rb create mode 100644 spec/extensions/guardian_extension_spec.rb diff --git a/extensions/guardian.rb b/extensions/guardian.rb new file mode 100644 index 00000000..2474b49b --- /dev/null +++ b/extensions/guardian.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true +module CustomWizardGuardian + def can_see_topic?(topic, hide_deleted = true) + wizard_user_can_create_topic_on_category?(topic) || super + end + + def can_edit_topic?(topic) + wizard_user_can_create_topic_on_category?(topic) || super + end + + def can_create_post?(parent) + result = parent.present? ? wizard_user_can_create_topic_on_category?(parent) : false + result || super + end + + private + + def wizard_user_can_create_topic_on_category?(topic) + wizard = creating_wizard(topic) + (wizard.present? && wizard.permitted? && wizard_can_create_topic_on_category?(wizard, topic)) + end + + def creating_wizard(topic) + wizard_id = topic.wizard_created.presence + wizard = CustomWizard::Builder.new(wizard_id, @user).build if wizard_id + return wizard.presence + end + + def wizard_can_create_topic_on_category?(wizard, topic) + return false unless topic.category.present? + + wizard_actions = wizard.actions + return false if wizard_actions.empty? + + create_topic_actions = wizard_actions.select do |action| + action['type'] === 'create_topic' + end + + submission_data = begin + submissions = CustomWizard::Submission.list(wizard) + submissions.find { |sub| sub.id == topic.wizard_submission }&.fields_and_meta + end + + categories = wizard_actions.map do |action| + category = CustomWizard::Mapper.new( + inputs: action['category'], + data: submission_data, + user: @user + ).perform + + category + end + + categories.flatten! + + return true if categories.include?(topic.category.id) + false + end +end diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index 9245a591..b2ce05bc7 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -514,7 +514,13 @@ class CustomWizard::Action def basic_topic_params params = { - skip_validations: true + skip_validations: true, + topic_opts: { + custom_fields: { + wizard_created: @wizard.id, + wizard_submission: @wizard.current_submission.id + } + } } params[:title] = CustomWizard::Mapper.new( diff --git a/lib/custom_wizard/guardian.rb b/lib/custom_wizard/guardian.rb deleted file mode 100644 index c453f509..00000000 --- a/lib/custom_wizard/guardian.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true -class CustomWizard::Guardian - def initialize(user) - @user = user - end - - def can_edit_topic?(topic) - creating_wizard = topic.wizard_created.presence - return false unless creating_wizard - - wizard_builder = CustomWizard::Builder.new(creating_wizard, @user) - wizard = wizard_builder.build - wizard_actions = wizard.actions - return false if wizard_actions.empty? - - create_topic_action = wizard_actions.find do |action| - action['type'] === 'create_topic' - end - - return wizard_can_create_topic_on_category?(action, topic) - end - - private - - def wizard_can_create_topic_on_category?(action, topic) - return false unless topic.category.present? - - category = CustomWizard::Mapper.new( - inputs: action['category'], - data: - ) - end -end diff --git a/plugin.rb b/plugin.rb index d412c76b..1592ac30 100644 --- a/plugin.rb +++ b/plugin.rb @@ -86,7 +86,6 @@ after_initialize do ../lib/custom_wizard/submission.rb ../lib/custom_wizard/template.rb ../lib/custom_wizard/wizard.rb - ../lib/custom_wizard/guardian.rb ../lib/custom_wizard/api/api.rb ../lib/custom_wizard/api/authorization.rb ../lib/custom_wizard/api/endpoint.rb @@ -109,6 +108,7 @@ after_initialize do ../serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb ../extensions/extra_locales_controller.rb ../extensions/invites_controller.rb + ../extensions/guardian.rb ../extensions/users_controller.rb ../extensions/custom_field/preloader.rb ../extensions/custom_field/serializer.rb @@ -119,6 +119,14 @@ after_initialize do Liquid::Template.register_filter(::CustomWizard::LiquidFilter::FirstNonEmpty) + add_to_class(:topic, :wizard_created) do + custom_fields['wizard_created'] + end + + add_to_class(:topic, :wizard_submission) do + custom_fields['wizard_submission'] + end + add_class_method(:wizard, :user_requires_completion?) do |user| wizard_result = self.new(user).requires_completion? return wizard_result if wizard_result @@ -192,6 +200,7 @@ after_initialize do ::ExtraLocalesController.prepend ExtraLocalesControllerCustomWizard ::InvitesController.prepend InvitesControllerCustomWizard ::UsersController.prepend CustomWizardUsersController + ::Guardian.prepend CustomWizardGuardian full_path = "#{Rails.root}/plugins/discourse-custom-wizard/assets/stylesheets/wizard/wizard_custom.scss" if Stylesheet::Importer.respond_to?(:plugin_assets) diff --git a/spec/components/custom_wizard/guardian_spec.rb b/spec/components/custom_wizard/guardian_spec.rb deleted file mode 100644 index bb7578d2..00000000 --- a/spec/components/custom_wizard/guardian_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true -require_relative '../../plugin_helper' - -describe CustomWizard::Guardian do - -end diff --git a/spec/extensions/guardian_extension_spec.rb b/spec/extensions/guardian_extension_spec.rb new file mode 100644 index 00000000..09edd1d6 --- /dev/null +++ b/spec/extensions/guardian_extension_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true +require_relative '../plugin_helper' + +describe ::Guardian do + fab!(:user) { + Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com") + } + fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') } + let(:wizard_template) { + JSON.parse( + File.open( + "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" + ).read + ) + } + + before do + CustomWizard::Template.save(wizard_template, skip_jobs: true) + @template = CustomWizard::Template.find('super_mega_fun_wizard') + end + + context "the user has access to creating wizard" do + it "allows editing the topic first post" do + wizard = CustomWizard::Builder.new(@template[:id], user).build + + wizard.create_updater( + wizard.steps.first.id, + step_1_field_1: "Topic Title", + step_1_field_2: "topic body" + ).update + wizard.create_updater(wizard.steps.second.id, {}).update + wizard.create_updater(wizard.steps.last.id, + step_3_field_3: category.id + ).update + + topic = Topic.where( + title: "Topic Title", + category_id: category.id + ).first + + expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_truthy + end + end + + context "the user doesn't have access to creating wizard" do + it "restricts editing the topic first post" do + wizard = CustomWizard::Builder.new(@template[:id], user).build + CustomWizard::Wizard.any_instance.stubs(:permitted?).returns(false) + + wizard.create_updater( + wizard.steps.first.id, + step_1_field_1: "Topic Title", + step_1_field_2: "topic body" + ).update + wizard.create_updater(wizard.steps.second.id, {}).update + wizard.create_updater(wizard.steps.last.id, + step_3_field_3: category.id + ).update + + topic = Topic.where( + title: "Topic Title", + category_id: category.id + ).first + + expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_falsey + end + end +end From dec5f5b5cebaf8d872056ee792c69323e0b95d31 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Sat, 30 Oct 2021 16:03:30 +0530 Subject: [PATCH 3/6] added more specs and fixed formatting --- extensions/guardian.rb | 4 +-- spec/extensions/guardian_extension_spec.rb | 29 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/extensions/guardian.rb b/extensions/guardian.rb index 2474b49b..f00cf9e8 100644 --- a/extensions/guardian.rb +++ b/extensions/guardian.rb @@ -9,7 +9,7 @@ module CustomWizardGuardian end def can_create_post?(parent) - result = parent.present? ? wizard_user_can_create_topic_on_category?(parent) : false + result = parent.present? ? wizard_user_can_create_topic_on_category?(parent) : false result || super end @@ -23,7 +23,7 @@ module CustomWizardGuardian def creating_wizard(topic) wizard_id = topic.wizard_created.presence wizard = CustomWizard::Builder.new(wizard_id, @user).build if wizard_id - return wizard.presence + wizard.presence end def wizard_can_create_topic_on_category?(wizard, topic) diff --git a/spec/extensions/guardian_extension_spec.rb b/spec/extensions/guardian_extension_spec.rb index 09edd1d6..50e2ebe4 100644 --- a/spec/extensions/guardian_extension_spec.rb +++ b/spec/extensions/guardian_extension_spec.rb @@ -2,7 +2,7 @@ require_relative '../plugin_helper' describe ::Guardian do - fab!(:user) { + fab!(:user) { Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com") } fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') } @@ -65,4 +65,31 @@ describe ::Guardian do expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_falsey end end + + context "the wizard can't create a topic in the category" do + it "restricts editing the topic first post" do + wizard = CustomWizard::Builder.new(@template[:id], user).build + wizard.create_updater( + wizard.steps.first.id, + step_1_field_1: "Topic Title", + step_1_field_2: "topic body" + ).update + wizard.create_updater(wizard.steps.second.id, {}).update + wizard.create_updater(wizard.steps.last.id, + step_3_field_3: category.id + ).update + + topic = Topic.where( + title: "Topic Title", + category_id: category.id + ).first + + new_category = Fabricate(:category) + topic.category_id = new_category.id + topic.save + topic.reload + + expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_falsey + end + end end From b7575a3295265e06ebf2e6203d326cccfc177f28 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Sat, 30 Oct 2021 16:07:16 +0530 Subject: [PATCH 4/6] use standard naming for custom fields --- extensions/guardian.rb | 4 ++-- lib/custom_wizard/action.rb | 4 ++-- plugin.rb | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/guardian.rb b/extensions/guardian.rb index f00cf9e8..96ceda93 100644 --- a/extensions/guardian.rb +++ b/extensions/guardian.rb @@ -21,7 +21,7 @@ module CustomWizardGuardian end def creating_wizard(topic) - wizard_id = topic.wizard_created.presence + wizard_id = topic.wizard_id.presence wizard = CustomWizard::Builder.new(wizard_id, @user).build if wizard_id wizard.presence end @@ -38,7 +38,7 @@ module CustomWizardGuardian submission_data = begin submissions = CustomWizard::Submission.list(wizard) - submissions.find { |sub| sub.id == topic.wizard_submission }&.fields_and_meta + submissions.find { |sub| sub.id == topic.wizard_submission_id }&.fields_and_meta end categories = wizard_actions.map do |action| diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index b2ce05bc7..0c2532ef 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -517,8 +517,8 @@ class CustomWizard::Action skip_validations: true, topic_opts: { custom_fields: { - wizard_created: @wizard.id, - wizard_submission: @wizard.current_submission.id + wizard_id: @wizard.id, + wizard_submission_id: @wizard.current_submission.id } } } diff --git a/plugin.rb b/plugin.rb index 4dbce4b4..961e45cd 100644 --- a/plugin.rb +++ b/plugin.rb @@ -119,12 +119,12 @@ after_initialize do Liquid::Template.register_filter(::CustomWizard::LiquidFilter::FirstNonEmpty) - add_to_class(:topic, :wizard_created) do - custom_fields['wizard_created'] + add_to_class(:topic, :wizard_id) do + custom_fields['wizard_id'] end - add_to_class(:topic, :wizard_submission) do - custom_fields['wizard_submission'] + add_to_class(:topic, :wizard_submission_id) do + custom_fields['wizard_submission_id'] end add_class_method(:wizard, :user_requires_completion?) do |user| From 4b0008ee52025015d23b3e09b1dacd0dda420898 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Sat, 30 Oct 2021 16:09:38 +0530 Subject: [PATCH 5/6] version bump --- plugin.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.rb b/plugin.rb index 961e45cd..532e69e8 100644 --- a/plugin.rb +++ b/plugin.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # name: discourse-custom-wizard # about: Create custom wizards -# version: 1.15.2 +# version: 1.15.3 # authors: Angus McLeod # url: https://github.com/paviliondev/discourse-custom-wizard # contact emails: angus@thepavilion.io From f5a35baa1bc3ee28246cd6721127feac4c26146f Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Mon, 31 Jan 2022 12:50:20 +0530 Subject: [PATCH 6/6] simplified logic --- extensions/guardian.rb | 62 +++----------- lib/custom_wizard/action.rb | 1 - plugin.rb | 4 - spec/extensions/guardian_extension_spec.rb | 94 +++++++--------------- 4 files changed, 40 insertions(+), 121 deletions(-) diff --git a/extensions/guardian.rb b/extensions/guardian.rb index 96ceda93..bbfe6f41 100644 --- a/extensions/guardian.rb +++ b/extensions/guardian.rb @@ -1,59 +1,17 @@ # frozen_string_literal: true + module CustomWizardGuardian - def can_see_topic?(topic, hide_deleted = true) - wizard_user_can_create_topic_on_category?(topic) || super - end - def can_edit_topic?(topic) - wizard_user_can_create_topic_on_category?(topic) || super + wizard_can_edit_topic?(topic) || super end - def can_create_post?(parent) - result = parent.present? ? wizard_user_can_create_topic_on_category?(parent) : false - result || super - end - - private - - def wizard_user_can_create_topic_on_category?(topic) - wizard = creating_wizard(topic) - (wizard.present? && wizard.permitted? && wizard_can_create_topic_on_category?(wizard, topic)) - end - - def creating_wizard(topic) - wizard_id = topic.wizard_id.presence - wizard = CustomWizard::Builder.new(wizard_id, @user).build if wizard_id - wizard.presence - end - - def wizard_can_create_topic_on_category?(wizard, topic) - return false unless topic.category.present? - - wizard_actions = wizard.actions - return false if wizard_actions.empty? - - create_topic_actions = wizard_actions.select do |action| - action['type'] === 'create_topic' - end - - submission_data = begin - submissions = CustomWizard::Submission.list(wizard) - submissions.find { |sub| sub.id == topic.wizard_submission_id }&.fields_and_meta - end - - categories = wizard_actions.map do |action| - category = CustomWizard::Mapper.new( - inputs: action['category'], - data: submission_data, - user: @user - ).perform - - category - end - - categories.flatten! - - return true if categories.include?(topic.category.id) - false + def wizard_can_edit_topic?(topic) + created_by_wizard = !!topic.wizard_submission_id + ( + is_my_own?(topic) && + created_by_wizard && + can_see_topic?(topic) && + can_create_post_on_topic?(topic) + ) end end diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index 0c2532ef..1e1c410c 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -517,7 +517,6 @@ class CustomWizard::Action skip_validations: true, topic_opts: { custom_fields: { - wizard_id: @wizard.id, wizard_submission_id: @wizard.current_submission.id } } diff --git a/plugin.rb b/plugin.rb index dbdf8cd5..94f9059b 100644 --- a/plugin.rb +++ b/plugin.rb @@ -126,10 +126,6 @@ after_initialize do Liquid::Template.register_filter(::CustomWizard::LiquidFilter::FirstNonEmpty) - add_to_class(:topic, :wizard_id) do - custom_fields['wizard_id'] - end - add_to_class(:topic, :wizard_submission_id) do custom_fields['wizard_submission_id'] end diff --git a/spec/extensions/guardian_extension_spec.rb b/spec/extensions/guardian_extension_spec.rb index 50e2ebe4..d779fe11 100644 --- a/spec/extensions/guardian_extension_spec.rb +++ b/spec/extensions/guardian_extension_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative '../plugin_helper' describe ::Guardian do @@ -14,82 +15,47 @@ describe ::Guardian do ) } + def create_topic_by_wizard(wizard) + wizard.create_updater( + wizard.steps.first.id, + step_1_field_1: "Topic Title", + step_1_field_2: "topic body" + ).update + wizard.create_updater(wizard.steps.second.id, {}).update + wizard.create_updater(wizard.steps.last.id, + step_3_field_3: category.id + ).update + + topic = Topic.where( + title: "Topic Title", + category_id: category.id + ).first + + topic + end + before do CustomWizard::Template.save(wizard_template, skip_jobs: true) @template = CustomWizard::Template.find('super_mega_fun_wizard') end - context "the user has access to creating wizard" do + context "topic created by user using wizard" do it "allows editing the topic first post" do wizard = CustomWizard::Builder.new(@template[:id], user).build - - wizard.create_updater( - wizard.steps.first.id, - step_1_field_1: "Topic Title", - step_1_field_2: "topic body" - ).update - wizard.create_updater(wizard.steps.second.id, {}).update - wizard.create_updater(wizard.steps.last.id, - step_3_field_3: category.id - ).update - - topic = Topic.where( - title: "Topic Title", - category_id: category.id - ).first - - expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_truthy + topic = create_topic_by_wizard(wizard) + expect(user.guardian.wizard_can_edit_topic?(topic)).to be_truthy end end - context "the user doesn't have access to creating wizard" do + context "topic created by user without wizard" do it "restricts editing the topic first post" do - wizard = CustomWizard::Builder.new(@template[:id], user).build - CustomWizard::Wizard.any_instance.stubs(:permitted?).returns(false) - - wizard.create_updater( - wizard.steps.first.id, - step_1_field_1: "Topic Title", - step_1_field_2: "topic body" - ).update - wizard.create_updater(wizard.steps.second.id, {}).update - wizard.create_updater(wizard.steps.last.id, - step_3_field_3: category.id - ).update - - topic = Topic.where( + topic_params = { title: "Topic Title", - category_id: category.id - ).first - - expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_falsey - end - end - - context "the wizard can't create a topic in the category" do - it "restricts editing the topic first post" do - wizard = CustomWizard::Builder.new(@template[:id], user).build - wizard.create_updater( - wizard.steps.first.id, - step_1_field_1: "Topic Title", - step_1_field_2: "topic body" - ).update - wizard.create_updater(wizard.steps.second.id, {}).update - wizard.create_updater(wizard.steps.last.id, - step_3_field_3: category.id - ).update - - topic = Topic.where( - title: "Topic Title", - category_id: category.id - ).first - - new_category = Fabricate(:category) - topic.category_id = new_category.id - topic.save - topic.reload - - expect(user.guardian.send(:wizard_user_can_create_topic_on_category?, topic)).to be_falsey + raw: "Topic body", + skip_validations: true + } + post = PostCreator.new(user, topic_params).create + expect(user.guardian.wizard_can_edit_topic?(post.topic)).to be_falsey end end end