From edc94b6ea7d86b6f570d167242bf4346d736a754 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Wed, 8 Feb 2023 13:32:24 +0100 Subject: [PATCH] Restrict guest support to standard and business subscriptions - Support mapped value subscription restrictions - Restrict permitted guest value to standard and business --- .../components/wizard-mapper-selector.js.es6 | 32 +++++++++++-------- config/locales/server.en.yml | 2 +- lib/custom_wizard/mapper.rb | 4 +++ lib/custom_wizard/subscription.rb | 28 ++++++++++++++-- .../custom_wizard/subscription_spec.rb | 14 +++++++- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 index 811564a5..e19e4917 100644 --- a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 +++ b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 @@ -15,6 +15,7 @@ import { import Component from "@ember/component"; import { bind, later } from "@ember/runloop"; import I18n from "I18n"; +import Subscription from "../mixins/subscription"; const customFieldActionMap = { topic: ["create_topic", "send_message"], @@ -26,7 +27,7 @@ const customFieldActionMap = { const values = ["present", "true", "false"]; -export default Component.extend({ +export default Component.extend(Subscription, { classNameBindings: [":mapper-selector", "activeType"], showText: computed("activeType", function () { @@ -129,24 +130,27 @@ export default Component.extend({ return this.connector === "is"; }), - @discourseComputed("site.groups", "guestGroup") - groups(groups, guestGroup) { + @discourseComputed("site.groups", "guestGroup", "subscriptionType") + groups(groups, guestGroup, subscriptionType) { let result = groups; if (!guestGroup) { return result; } - let guestIndex; - result.forEach((r, index) => { - if (r.id === 0) { - r.name = I18n.t("admin.wizard.selector.label.users"); - guestIndex = index; - } - }); - result.splice(guestIndex, 0, { - id: -1, - name: I18n.t("admin.wizard.selector.label.guests"), - }); + if (["standard", "business"].includes(subscriptionType)) { + let guestIndex; + result.forEach((r, index) => { + if (r.id === 0) { + r.name = I18n.t("admin.wizard.selector.label.users"); + guestIndex = index; + } + }); + result.splice(guestIndex, 0, { + id: -1, + name: I18n.t("admin.wizard.selector.label.guests"), + }); + } + return result; }, categories: alias("site.categories"), diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index b283364e..e8ceb44b 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -53,7 +53,7 @@ en: after_signup_after_time: "You can't use 'after time' and 'after signup' on the same wizard." after_time: "After time setting is invalid." liquid_syntax_error: "Liquid syntax error in %{attribute}: %{message}" - subscription: "%{type} %{property} is subscription only" + subscription: "%{type} %{property} usage is not supported on your subscription" not_permitted_for_guests: "%{object_id} is not permitted when guests can access the wizard" site_settings: diff --git a/lib/custom_wizard/mapper.rb b/lib/custom_wizard/mapper.rb index e4d0db50..410a50e4 100644 --- a/lib/custom_wizard/mapper.rb +++ b/lib/custom_wizard/mapper.rb @@ -284,4 +284,8 @@ class CustomWizard::Mapper user.avatar_template_url.gsub("{size}", parts.last) end end + + def self.mapped_value?(value) + value.is_a?(Array) && value.all? { |v| v.is_a?(Hash) && v.key?("type") } + end end diff --git a/lib/custom_wizard/subscription.rb b/lib/custom_wizard/subscription.rb index c3c9803d..dfb75324 100644 --- a/lib/custom_wizard/subscription.rb +++ b/lib/custom_wizard/subscription.rb @@ -17,7 +17,7 @@ class CustomWizard::Subscription none: [], standard: ['*'], business: ['*'], - community: ['*'] + community: ['*', "!#{CustomWizard::Wizard::GUEST_GROUP_ID}"] }, restart_on_revisit: { none: [], @@ -114,8 +114,15 @@ class CustomWizard::Subscription ## Subscription type does not support the attribute. return false if values.blank? + ## Value is an exception for the subscription type + if (exceptions = get_exceptions(values)).any? + value = mapped_output(value) if CustomWizard::Mapper.mapped_value?(value) + value = [*value].map(&:to_s) + return false if (exceptions & value).length > 0 + end + ## Subscription type supports all values of the attribute. - return true if values.first === "*" + return true if values.include?("*") ## Subscription type supports some values of the attributes. values.include?(value) @@ -192,4 +199,21 @@ class CustomWizard::Subscription def self.includes?(feature, attribute, value) new.includes?(feature, attribute, value) end + + protected + + def get_exceptions(values) + values.reduce([]) do |result, value| + result << value.split("!").last if value.start_with?("!") + result + end + end + + def mapped_output(value) + value.reduce([]) do |result, v| + ## We can only validate mapped assignment values at the moment + result << v["output"] if v.is_a?(Hash) && v["type"] === "assignment" + result + end.flatten + end end diff --git a/spec/components/custom_wizard/subscription_spec.rb b/spec/components/custom_wizard/subscription_spec.rb index 5f06397b..2ac191e1 100644 --- a/spec/components/custom_wizard/subscription_spec.rb +++ b/spec/components/custom_wizard/subscription_spec.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true describe CustomWizard::Subscription do + let(:guests_permitted) { get_wizard_fixture("wizard/guests_permitted") } + def undefine_client_classes Object.send(:remove_const, :SubscriptionClient) if Object.constants.include?(:SubscriptionClient) Object.send(:remove_const, :SubscriptionClientSubscription) if Object.constants.include?(:SubscriptionClientSubscription) @@ -40,7 +42,7 @@ describe CustomWizard::Subscription do expect(described_class.includes?(:wizard, :after_signup, true)).to eq(true) end - it "ubscriber features are not included" do + it "subscriber features are not included" do expect(described_class.includes?(:wizard, :permitted, {})).to eq(false) end end @@ -69,6 +71,16 @@ describe CustomWizard::Subscription do end end + context "with a subscription" do + it "handles mapped values" do + SubscriptionClientSubscription.stubs(:product_id).returns(CustomWizard::Subscription::STANDARD_PRODUCT_ID) + expect(described_class.includes?(:wizard, :permitted, guests_permitted["permitted"])).to eq(true) + + SubscriptionClientSubscription.stubs(:product_id).returns(CustomWizard::Subscription::COMMUNITY_PRODUCT_ID) + expect(described_class.includes?(:wizard, :permitted, guests_permitted["permitted"])).to eq(false) + end + end + context "with standard subscription" do before do SubscriptionClientSubscription.stubs(:product_id).returns(CustomWizard::Subscription::STANDARD_PRODUCT_ID)