diff --git a/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 b/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 index 8332b86e..04123e3d 100644 --- a/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 +++ b/assets/javascripts/discourse/components/wizard-realtime-validations.js.es6 @@ -6,7 +6,8 @@ import discourseComputed from "discourse-common/utils/decorators"; import I18n from "I18n"; export default Component.extend({ - classNames: ["realtime-validations"], + classNames: ["realtime-validations", "setting", "full", "pro"], + @discourseComputed timeUnits() { return ["days", "weeks", "months", "years"].map((unit) => { diff --git a/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 index 332efedd..edb06ad9 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6 @@ -77,7 +77,12 @@ export default Controller.extend({ wizard .save(opts) .then((result) => { - this.send("afterSave", result.wizard_id); + console.log(result) + if (result.wizard_id) { + this.send("afterSave", result.wizard_id); + } else if (result.errors) { + this.set('error', result.errors.join(', ')); + } }) .catch((result) => { let errorType = "failed"; diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs index 9237cf62..afdbd767 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs @@ -220,60 +220,54 @@ options=fieldConditionOptions}} -{{/if}} + +
+
+ + {{i18n "admin.wizard.pro.label"}} +
-{{#if showAdvanced}} - {{wizard-advanced-toggle showAdvanced=field.showAdvanced}} +
+ {{wizard-mapper + inputs=field.index + options=fieldIndexOptions}} +
+
- {{#if field.showAdvanced}} -
- -
-
- -
- -
- {{wizard-mapper - inputs=field.index - options=fieldIndexOptions}} -
+ {{#if isCategory}} +
+
+ + {{i18n "admin.wizard.pro.label"}}
- - {{#if isCategory}} -
-
- -
- -
- {{combo-box - value=field.property - content=categoryPropertyTypes - onChange=(action (mut field.property)) - options=(hash - none="admin.wizard.selector.placeholder.property" - )}} -
-
- {{/if}} - -
-
- -
-
- {{input - name="key" - value=field.key - class="medium" - placeholderKey="admin.wizard.translation_placeholder"}} -
+ +
+ {{combo-box + value=field.property + content=categoryPropertyTypes + onChange=(action (mut field.property)) + options=(hash + none="admin.wizard.selector.placeholder.property" + )}}
- - {{#if validations}} - {{wizard-realtime-validations field=field validations=validations}} - {{/if}}
{{/if}} + +
+
+ + {{i18n "admin.wizard.pro.label"}} +
+
+ {{input + name="key" + value=field.key + class="medium" + placeholderKey="admin.wizard.translation_placeholder"}} +
+
+ + {{#if validations}} + {{wizard-realtime-validations field=field validations=validations}} + {{/if}} {{/if}} diff --git a/assets/javascripts/discourse/templates/components/wizard-pro-subscription.hbs b/assets/javascripts/discourse/templates/components/wizard-pro-subscription.hbs index 72631bfd..2bebc9ed 100644 --- a/assets/javascripts/discourse/templates/components/wizard-pro-subscription.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-pro-subscription.hbs @@ -21,8 +21,11 @@ {{#if subscribed}}
{{stateLabel}}
-
- {{{i18n 'admin.wizard.pro.subscription.last_updated' updated_at=(format-date subscription.updated_at leaveAgo="true")}}} -
+ + {{#if subscription.updated_at}} +
+ {{{i18n 'admin.wizard.pro.subscription.last_updated' updated_at=(format-date subscription.updated_at leaveAgo="true")}}} +
+ {{/if}}
{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs b/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs index cd1298a9..0cc34f35 100644 --- a/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-realtime-validations.hbs @@ -1,50 +1,54 @@ -

{{i18n "admin.wizard.field.validations.header"}}

- -
    - {{#each-in field.validations as |type props|}} -
  • - -

    {{i18n (concat "admin.wizard.field.validations." type)}}

    - {{input type="checkbox" checked=props.status}} - {{i18n "admin.wizard.field.validations.enabled"}} -
    -
    -
    -
    - +
    + + {{i18n "admin.wizard.pro.label"}} +
    +
    +
      + {{#each-in field.validations as |type props|}} +
    • + +

      {{i18n (concat "admin.wizard.field.validations." type)}}

      + {{input type="checkbox" checked=props.status}} + {{i18n "admin.wizard.field.validations.enabled"}} +
      +
      +
      +
      + +
      +
      + {{category-selector + categories=(get this (concat "validationBuffer." type ".categories")) + onChange=(action "updateValidationCategories" type props) + class="wizard"}} +
      -
      - {{category-selector - categories=(get this (concat "validationBuffer." type ".categories")) - onChange=(action "updateValidationCategories" type props) - class="wizard"}} +
      +
      + +
      +
      + {{input type="number" class="time-n-value" value=props.time_n_value}} + {{combo-box + value=(readonly props.time_unit) + content=timeUnits + class="time-unit-selector" + onChange=(action (mut props.time_unit))}} +
      +
      +
      +
      + +
      +
      + {{radio-button name=(concat type field.id) value="above" selection=props.position}} + {{i18n "admin.wizard.field.validations.above"}} + {{radio-button name=(concat type field.id) value="below" selection=props.position}} + {{i18n "admin.wizard.field.validations.below"}} +
      -
      -
      - -
      -
      - {{input type="number" class="time-n-value" value=props.time_n_value}} - {{combo-box - value=(readonly props.time_unit) - content=timeUnits - class="time-unit-selector" - onChange=(action (mut props.time_unit))}} -
      -
      -
      -
      - -
      -
      - {{radio-button name=(concat type field.id) value="above" selection=props.position}} - {{i18n "admin.wizard.field.validations.above"}} - {{radio-button name=(concat type field.id) value="below" selection=props.position}} - {{i18n "admin.wizard.field.validations.below"}} -
      -
      -
      -
    • - {{/each-in}} -
    +
  • + {{/each-in}} +
+
\ No newline at end of file diff --git a/assets/stylesheets/common/wizard-admin.scss b/assets/stylesheets/common/wizard-admin.scss index cca03c74..178dbc81 100644 --- a/assets/stylesheets/common/wizard-admin.scss +++ b/assets/stylesheets/common/wizard-admin.scss @@ -694,27 +694,59 @@ } } -.realtime-validations > ul { +.admin-wizard-container.settings .realtime-validations .setting-value > ul { list-style: none; margin: 0; + width: 100%; + display: flex; + flex-wrap: wrap; > li { background-color: var(--primary-low); padding: 1em; margin: 0 0 1em 0; + + .setting-title { + display: flex; + align-items: center; - input { - margin-bottom: 0; + h4 { + margin: 0 15px 0 0; + } + + input[type="checkbox"] { + margin: 0 5px 0 0; + } + } + + .setting-label { + width: 100px; + } + + .setting-value { + display: flex; + align-items: center; + + .input .select-kit, + > .select-kit { + max-width: unset !important; + } + + > span { + margin-right: 1em; + } } } } .validation-container { display: flex; + flex-direction: column; padding: 1em 0; .validation-section { - width: 250px; + min-width: 250px; + margin: .5em 0; } } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 4a2bf28f..bfea46ce 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -192,7 +192,7 @@ en: label: "Format" instructions: "Moment.js format" validations: - header: "Realtime Validations" + header: "Validations" enabled: "Enabled" similar_topics: "Similar Topics" position: "Position" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 86968fda..fffa01cc 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -17,7 +17,7 @@ en: name_too_short: "'%{name}' is too short for a custom field name (min length is #{min_length})" name_already_taken: "'%{name}' is already taken as a custom field name" save_default: "Failed to save custom field '%{name}'" - pro_required: "PRO Actions require a PRO Subscription" + pro_type: "%{type} custom fields require PRO Subscription" field: too_short: "%{label} must be at least %{min} characters" @@ -50,7 +50,7 @@ en: required: "%{property} is required" conflict: "Wizard with id '%{wizard_id}' already exists" after_time: "After time setting is invalid" - pro: "%{property} is PRO only" + pro: "%{type} %{property} is PRO only" site_settings: custom_wizard_enabled: "Enable custom wizards." diff --git a/config/routes.rb b/config/routes.rb index 94cc5858..abe36479 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -47,7 +47,7 @@ Discourse::Application.routes.append do get 'admin/wizards/pro' => 'admin_pro#index' get 'admin/wizards/pro/authorize' => 'admin_pro#authorize' get 'admin/wizards/pro/authorize/callback' => 'admin_pro#authorize_callback' - delete 'admin/wizards/pro/authorize' => 'admin_pro#destroy' + delete 'admin/wizards/pro/authorize' => 'admin_pro#destroy_authentication' post 'admin/wizards/pro/subscription' => 'admin_pro#update_subscription' end end diff --git a/controllers/custom_wizard/admin/pro.rb b/controllers/custom_wizard/admin/pro.rb index 9f32045e..15e9e50f 100644 --- a/controllers/custom_wizard/admin/pro.rb +++ b/controllers/custom_wizard/admin/pro.rb @@ -4,27 +4,27 @@ class CustomWizard::AdminProController < CustomWizard::AdminController skip_before_action :check_xhr, :preload_json, :verify_authenticity_token, only: [:authorize, :authorize_callback] def index - render_serialized(CustomWizard::Pro.new, CustomWizard::ProSerializer, root: false) + render_serialized(pro, CustomWizard::ProSerializer, root: false) end def authorize request_id = SecureRandom.hex(32) cookies[:user_api_request_id] = request_id - redirect_to CustomWizard::Pro.auth_request(current_user.id, request_id).to_s + redirect_to pro.authentication_request(current_user.id, request_id).to_s end def authorize_callback payload = params[:payload] request_id = cookies[:user_api_request_id] - CustomWizard::Pro.auth_response(request_id, payload) - CustomWizard::Pro.update_subscription + pro.authentication_response(request_id, payload) + pro.update_subscription redirect_to '/admin/wizards/pro' end - def destroy - if CustomWizard::ProAuthentication.destroy + def destroy_authentication + if pro.destroy_authentication render json: success_json else render json: failed_json @@ -32,15 +32,17 @@ class CustomWizard::AdminProController < CustomWizard::AdminController end def update_subscription - if CustomWizard::Pro.update - render json: success_json.merge( - subscription: CustomWizard::ProSubscriptionSerializer.new( - CustomWizard::ProSubscription.new, - root: false - ) - ) + if pro.update_subscription + subscription = CustomWizard::ProSubscriptionSerializer.new(pro.subscription, root: false) + render json: success_json.merge(subscription: subscription) else render json: failed_json end end + + protected + + def pro + @pro ||= CustomWizard::Pro.new + end end \ No newline at end of file diff --git a/controllers/custom_wizard/wizard.rb b/controllers/custom_wizard/wizard.rb index e0cf669d..804fc422 100644 --- a/controllers/custom_wizard/wizard.rb +++ b/controllers/custom_wizard/wizard.rb @@ -5,6 +5,7 @@ class CustomWizard::WizardController < ::ApplicationController layout 'wizard' before_action :ensure_plugin_enabled + before_action :update_pro_subscription helper_method :wizard_page_title helper_method :wizard_theme_id helper_method :wizard_theme_lookup @@ -81,4 +82,8 @@ class CustomWizard::WizardController < ::ApplicationController redirect_to path("/") end end + + def update_pro_subscription + CustomWizard::Pro.update_subscription + end end diff --git a/jobs/scheduled/update_pro_status.rb b/jobs/scheduled/update_pro_subscription.rb similarity index 89% rename from jobs/scheduled/update_pro_status.rb rename to jobs/scheduled/update_pro_subscription.rb index 6f947304..d00b2560 100644 --- a/jobs/scheduled/update_pro_status.rb +++ b/jobs/scheduled/update_pro_subscription.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class CustomWizard::UpdateProSubscription < ::Jobs::Scheduled - every 10.minutes + every 1.hour def execute(args) CustomWizard::Pro.update_subscription diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index 1cadbb5b..74dc4680 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -14,15 +14,9 @@ class CustomWizard::Action @submission = opts[:submission] @log = [] @result = CustomWizard::ActionResult.new - @pro = CustomWizard::Pro.new end def perform - if pro_actions.include?(action['type']) && !@pro.subscribed? - log_error(I18n.t("wizard.custom_field.error.pro_required")) - return - end - ActiveRecord::Base.transaction do self.send(action['type'].to_sym) end diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb index 78a960b9..2ecdf12d 100644 --- a/lib/custom_wizard/builder.rb +++ b/lib/custom_wizard/builder.rb @@ -6,7 +6,6 @@ class CustomWizard::Builder @template = CustomWizard::Template.create(wizard_id) return nil if @template.nil? @wizard = CustomWizard::Wizard.new(template.data, user) - @pro = CustomWizard::Pro.new end def self.sorted_handlers @@ -226,11 +225,6 @@ class CustomWizard::Builder end def check_condition(template) - unless @pro.subscribed? - CustomWizard::Log.create(I18n.t("wizard.custom_field.error.pro_required")) - return false - end - if template['condition'].present? result = CustomWizard::Mapper.new( inputs: template['condition'], diff --git a/lib/custom_wizard/custom_field.rb b/lib/custom_wizard/custom_field.rb index 9cc185ba..cc20ee95 100644 --- a/lib/custom_wizard/custom_field.rb +++ b/lib/custom_wizard/custom_field.rb @@ -37,6 +37,8 @@ class ::CustomWizard::CustomField send("#{attr}=", value) end end + + @pro = CustomWizard::Pro.new end def save @@ -92,6 +94,10 @@ class ::CustomWizard::CustomField add_error(I18n.t("#{i18n_key}.unsupported_type", type: value)) end + if attr == 'type' && value == 'json' && !@pro.subscribed? + add_error(I18n.t("wizard.custom_field.error.pro_type", type: value)) + end + if attr == 'name' unless value.is_a?(String) add_error(I18n.t("#{i18n_key}.name_invalid", name: value)) diff --git a/lib/custom_wizard/mapper.rb b/lib/custom_wizard/mapper.rb index 0c3543cf..b418b4b9 100644 --- a/lib/custom_wizard/mapper.rb +++ b/lib/custom_wizard/mapper.rb @@ -47,6 +47,7 @@ class CustomWizard::Mapper @data = params[:data] || {} @user = params[:user] @opts = params[:opts] || {} + @pro = CustomWizard::Pro.new end def perform @@ -251,7 +252,7 @@ class CustomWizard::Mapper end end - if opts[:template] + if @pro.subscribed? && opts[:template] template = Liquid::Template.parse(string) string = template.render(data) end diff --git a/lib/custom_wizard/pro.rb b/lib/custom_wizard/pro.rb index f54dd92d..3726e9b4 100644 --- a/lib/custom_wizard/pro.rb +++ b/lib/custom_wizard/pro.rb @@ -1,12 +1,22 @@ # frozen_string_literal: true class CustomWizard::Pro - attr_reader :authentication, - :subscription + include ActiveModel::Serialization + + attr_accessor :authentication, + :subscription def initialize - @authentication = CustomWizard::ProAuthentication.new - @subscription = CustomWizard::ProSubscription.new + @authentication = CustomWizard::ProAuthentication.new(get_authentication) + @subscription = CustomWizard::ProSubscription.new(get_subscription) + end + + def authorized? + @authentication.active? + end + + def subscribed? + @subscription.active? end def server @@ -21,12 +31,8 @@ class CustomWizard::Pro "custom-wizard" end - def authorized? - @authentication.active? - end - - def subscribed? - @subscription.active? + def scope + "discourse-subscription-server:user_subscription" end def update_subscription @@ -45,28 +51,35 @@ class CustomWizard::Pro return false end - return @subscription.update(data) + return false unless data && data.is_a?(Hash) + subscriptions = data[:subscriptions] + + if subscriptions.present? + subscription = subscriptions.first + type = subscription[:price_nickname] + + @subscription = set_subscription(type) + return true + end end end - @subscription.destroy - false + remove_subscription end - def destroy - @authentication.destroy + def destroy_subscription + remove_subscription end - def auth_request(user_id, request_id) + def authentication_request(user_id, request_id) keys = @authentication.generate_keys(user_id, request_id) - params = { public_key: keys.public_key, nonce: keys.nonce, client_id: @authentication.client_id, auth_redirect: "#{Discourse.base_url}/admin/wizards/pro/authorize/callback", application_name: SiteSetting.title, - scopes: "discourse-subscription-server:user_subscription" + scopes: scope } uri = URI.parse("https://#{server}/user-api-key/new") @@ -74,26 +87,24 @@ class CustomWizard::Pro uri.to_s end - def auth_response(request_id, payload) + def authentication_response(request_id, payload) data = @authentication.decrypt_payload(request_id, payload) return unless data.is_a?(Hash) && data[:key] && data[:user_id] - @authentication.update(data) + + api_key = data[:key] + user_id = data[:user_id] + user = User.find(user_id) + + if user&.admin + @authentication = set_authentication(api_key, user.id) + true + else + false + end end - def self.update - self.new.update - end - - def self.destroy - self.new.destroy - end - - def self.generate_request - self.new.generate_request - end - - def self.handle_response - self.new.handle_response + def destroy_authentication + remove_authentication end def self.subscribed? @@ -103,4 +114,56 @@ class CustomWizard::Pro def self.namespace "custom_wizard_pro" end + + private + + def subscription_db_key + "subscription" + end + + def authentication_db_key + "authentication" + end + + def get_subscription + raw = PluginStore.get(self.class.namespace, subscription_db_key) + + if raw.present? + OpenStruct.new( + type: raw['type'], + updated_at: raw['updated_at'] + ) + end + end + + def remove_subscription + PluginStore.remove(self.class.namespace, subscription_db_key) + end + + def set_subscription(type) + PluginStore.set(CustomWizard::Pro.namespace, subscription_db_key, type: type, updated_at: Time.now) + CustomWizard::ProSubscription.new(get_subscription) + end + + def get_authentication + raw = PluginStore.get(self.class.namespace, authentication_db_key) + OpenStruct.new( + key: raw && raw['key'], + auth_by: raw && raw['auth_by'], + auth_at: raw && raw['auth_at'] + ) + end + + def set_authentication(key, user_id) + PluginStore.set(self.class.namespace, authentication_db_key, + key: key, + auth_by: user_id, + auth_at: Time.now + ) + CustomWizard::ProAuthentication.new(get_authentication) + end + + def remove_authentication + PluginStore.remove(self.class.namespace, authentication_db_key) + end end \ No newline at end of file diff --git a/lib/custom_wizard/pro/authentication.rb b/lib/custom_wizard/pro/authentication.rb index 0d89ab06..0f3546eb 100644 --- a/lib/custom_wizard/pro/authentication.rb +++ b/lib/custom_wizard/pro/authentication.rb @@ -6,12 +6,13 @@ class CustomWizard::ProAuthentication :auth_at, :api_key - def initialize - api = get_api_key + def initialize(auth) + if auth + @api_key = auth.key + @auth_at = auth.auth_at + @auth_by = auth.auth_by + end - @api_key = api.key - @auth_at = api.auth_at - @auth_by = api.auth_by @client_id = get_client_id || set_client_id end @@ -19,22 +20,6 @@ class CustomWizard::ProAuthentication @api_key.present? end - def update(data) - api_key = data[:key] - user_id = data[:user_id] - user = User.find(user_id) - - if user&.admin - set_api_key(api_key, user.id) - else - false - end - end - - def destroy - remove - end - def generate_keys(user_id, request_id) rsa = OpenSSL::PKey::RSA.generate(2048) nonce = SecureRandom.hex(32) @@ -63,50 +48,15 @@ class CustomWizard::ProAuthentication data end - + private - def api_key_db_key - "api_key" - end - - def api_client_id_db_key - "api_client_id" - end - def keys_db_key "keys" end - def get_api_key - raw = PluginStore.get(CustomWizard::Pro.namespace, api_key_db_key) - OpenStruct.new( - key: raw && raw['key'], - auth_by: raw && raw['auth_by'], - auth_at: raw && raw['auth_at'] - ) - end - - def set_api_key(key, user_id) - PluginStore.set(CustomWizard::Pro.namespace, api_key_db_key, - key: key, - auth_by: user_id, - auth_at: Time.now - ) - end - - def remove - PluginStore.remove(CustomWizard::Pro.namespace, api_key_db_key) - end - - def get_client_id - PluginStore.get(CustomWizard::Pro.namespace, api_client_id_db_key) - end - - def set_client_id - client_id = SecureRandom.hex(32) - PluginStore.set(CustomWizard::Pro.namespace, api_client_id_db_key, client_id) - client_id + def client_id_db_key + "client_id" end def set_keys(request_id, user_id, rsa, nonce) @@ -129,4 +79,14 @@ class CustomWizard::ProAuthentication def delete_keys(request_id) PluginStore.remove(CustomWizard::Pro.namespace, "#{keys_db_key}_#{request_id}") end + + def get_client_id + PluginStore.get(CustomWizard::Pro.namespace, client_id_db_key) + end + + def set_client_id + client_id = SecureRandom.hex(32) + PluginStore.set(CustomWizard::Pro.namespace, client_id_db_key, client_id) + client_id + end end \ No newline at end of file diff --git a/lib/custom_wizard/pro/subscription.rb b/lib/custom_wizard/pro/subscription.rb index f82b58df..a5782357 100644 --- a/lib/custom_wizard/pro/subscription.rb +++ b/lib/custom_wizard/pro/subscription.rb @@ -4,12 +4,10 @@ class CustomWizard::ProSubscription attr_reader :type, :updated_at - def initialize - raw = get - - if raw - @type = raw['type'] - @updated_at = raw['updated_at'] + def initialize(subscription) + if subscription + @type = subscription.type + @updated_at = subscription.updated_at end end @@ -18,40 +16,6 @@ class CustomWizard::ProSubscription end def active? - types.include?(type) && updated_at.to_datetime > (Date.today - 15.minutes).to_datetime - end - - def update(data) - return false unless data && data.is_a?(Hash) - subscriptions = data[:subscriptions] - - if subscriptions.present? - subscription = subscriptions.first - type = subscription[:price_nickname] - - set(type) - end - end - - def destroy - remove - end - - private - - def key - "custom_wizard_pro_subscription" - end - - def set(type) - PluginStore.set(CustomWizard::Pro.namespace, key, type: type, updated_at: Time.now) - end - - def get - PluginStore.get(CustomWizard::Pro.namespace, key) - end - - def remove - PluginStore.remove(CustomWizard::Pro.namespace, key) + types.include?(type) && updated_at.to_datetime > (Time.zone.now - 2.hours).to_datetime end end \ No newline at end of file diff --git a/lib/custom_wizard/validators/template.rb b/lib/custom_wizard/validators/template.rb index deaa5119..180958ba 100644 --- a/lib/custom_wizard/validators/template.rb +++ b/lib/custom_wizard/validators/template.rb @@ -31,6 +31,7 @@ class CustomWizard::TemplateValidator if data[:actions].present? data[:actions].each do |action| + validate_pro_action(action) check_required(action, :action) end end @@ -53,15 +54,31 @@ class CustomWizard::TemplateValidator def self.pro { - step: ['condition'], - field: ['conition'] + wizard: {}, + step: { + condition: 'present', + index: 'conditional' + }, + field: { + condition: 'present', + index: 'conditional' + }, + action: { + type: %w[ + send_message + create_category + create_group + watch_categories + send_to_api + ] + } } end private def check_required(object, type) - CustomWizard::TemplateValidator.required[type].each do |property| + self.class.required[type].each do |property| if object[property].blank? errors.add :base, I18n.t("wizard.validation.required", property: property) end @@ -69,9 +86,13 @@ class CustomWizard::TemplateValidator end def validate_pro(object, type) - CustomWizard::TemplateValidator.required[type].each do |property| - if object[property].present? && !@pro.subscribed? - errors.add :base, I18n.t("wizard.validation.pro", property: property) + self.class.pro[type].each do |property, pro_type| + is_pro = (pro_type === 'present' && object[property].present?) || + (pro_type === 'conditional' && object[property].is_a?(Hash)) || + (pro_type.is_a?(Array) && pro_type.includes?(object[property])) + + if is_pro && @pro.subscribed? + errors.add :base, I18n.t("wizard.validation.pro", type: type.to_s, property: property) end end end diff --git a/plugin.rb b/plugin.rb index 7c056b5d..b2c6d54c 100644 --- a/plugin.rb +++ b/plugin.rb @@ -69,7 +69,7 @@ after_initialize do ../controllers/custom_wizard/realtime_validations.rb ../jobs/regular/refresh_api_access_token.rb ../jobs/regular/set_after_time_wizard.rb - ../jobs/scheduled/update_pro_status.rb + ../jobs/scheduled/update_pro_subscription.rb ../lib/custom_wizard/validators/template.rb ../lib/custom_wizard/validators/update.rb ../lib/custom_wizard/action_result.rb @@ -111,9 +111,9 @@ after_initialize do ../serializers/custom_wizard/log_serializer.rb ../serializers/custom_wizard/submission_serializer.rb ../serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb - ../serializers/custom_wizard/pro_serializer.rb ../serializers/custom_wizard/pro/authentication_serializer.rb ../serializers/custom_wizard/pro/subscription_serializer.rb + ../serializers/custom_wizard/pro_serializer.rb ../extensions/extra_locales_controller.rb ../extensions/invites_controller.rb ../extensions/users_controller.rb @@ -126,18 +126,6 @@ after_initialize do Liquid::Template.register_filter(::CustomWizard::LiquidFilter::FirstNonEmpty) - class CustomWizard::UnpermittedOverride < StandardError; end - - CustomWizard.constants.each do |class_name| - klass = CustomWizard.const_get(class_name) - next if !klass.is_a?(Class) || klass.superclass.name.to_s.split("::").first == 'CustomWizard' - - klass.define_singleton_method(:prepend) { |klass| raise CustomWizard::UnpermittedOverride.new } - klass.define_singleton_method(:include) { |klass| raise CustomWizard::UnpermittedOverride.new } - klass.define_singleton_method(:define_method) { |name, &block| raise CustomWizard::UnpermittedOverride.new } - klass.define_singleton_method(:define_singleton_method) { |name, &block| raise CustomWizard::UnpermittedOverride.new } - end - add_class_method(:wizard, :user_requires_completion?) do |user| wizard_result = self.new(user).requires_completion? return wizard_result if wizard_result diff --git a/serializers/custom_wizard/pro_serializer.rb b/serializers/custom_wizard/pro_serializer.rb index 5b351f29..a9623974 100644 --- a/serializers/custom_wizard/pro_serializer.rb +++ b/serializers/custom_wizard/pro_serializer.rb @@ -1,26 +1,6 @@ # frozen_string_literal: true class CustomWizard::ProSerializer < ApplicationSerializer - attributes :server, - :authentication, - :subscription - - def server - CustomWizard::ProSubscription::SUBSCRIPTION_SERVER - end - - def authentication - if object.authentication - CustomWizard::ProAuthenticationSerializer.new(object.authentication, root: false) - else - nil - end - end - - def subscription - if object.subscription - CustomWizard::ProSubscriptionSerializer.new(object.subscription, root: false) - else - nil - end - end + attributes :server + has_one :authentication, serializer: CustomWizard::ProAuthenticationSerializer, embed: :objects + has_one :subscription, serializer: CustomWizard::ProSubscriptionSerializer, embed: :objects end \ No newline at end of file