diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..c799fa5a
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,7 @@
+# Security Policy
+
+The security of Discourse plugins are premised on the security of [Discourse](https://github.com/discourse/discourse). Please first consider whether a security issue is best reported and handled by the Discourse team. You can view the Discourse security policy [here](https://github.com/discourse/discourse/security/policy).
+
+## Reporting a Vulnerability
+
+If you find a security vulnerability that is specific to this plugin, please report it to development@pavilion.tech. Security issues always take precedence over all other work. All commits specific to security are prefixed with SECURITY.
diff --git a/app/controllers/custom_wizard/admin/wizard.rb b/app/controllers/custom_wizard/admin/wizard.rb
index c778bc7e..08e7b6d0 100644
--- a/app/controllers/custom_wizard/admin/wizard.rb
+++ b/app/controllers/custom_wizard/admin/wizard.rb
@@ -114,6 +114,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
:property,
:preview_template,
:placeholder,
+ :can_create_tag,
prefill: mapped_params,
content: mapped_params,
condition: mapped_params,
diff --git a/app/serializers/custom_wizard/wizard_field_serializer.rb b/app/serializers/custom_wizard/wizard_field_serializer.rb
index d5f57060..56e86cc8 100644
--- a/app/serializers/custom_wizard/wizard_field_serializer.rb
+++ b/app/serializers/custom_wizard/wizard_field_serializer.rb
@@ -17,6 +17,7 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
:property,
:content,
:tag_groups,
+ :can_create_tag,
:validations,
:max_length,
:char_counter,
@@ -98,6 +99,10 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
object.tag_groups
end
+ def can_create_tag
+ object.can_create_tag
+ end
+
def validations
validations = {}
object.validations&.each do |type, props|
diff --git a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6 b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6
index 92c56ea1..5e2ef424 100644
--- a/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6
+++ b/assets/javascripts/discourse/components/custom-wizard-composer-editor.js.es6
@@ -149,7 +149,7 @@ export default ComposerEditor.extend({
extraButtons(toolbar) {
const component = this;
- if (this.allowUpload && this.uploadIcon && !this.site.mobileView) {
+ if (this.allowUpload && this.uploadIcon) {
toolbar.addButton({
id: "upload",
group: "insertions",
diff --git a/assets/javascripts/discourse/components/wizard-text-editor.js.es6 b/assets/javascripts/discourse/components/wizard-text-editor.js.es6
index 88d7200c..b6d07cef 100644
--- a/assets/javascripts/discourse/components/wizard-text-editor.js.es6
+++ b/assets/javascripts/discourse/components/wizard-text-editor.js.es6
@@ -5,11 +5,7 @@ import { scheduleOnce } from "@ember/runloop";
import Component from "@ember/component";
import I18n from "I18n";
-const excludedUserProperties = [
- "avatar",
- "profile_background",
- "card_background",
-];
+const excludedUserProperties = ["profile_background", "card_background"];
export default Component.extend({
classNames: "wizard-text-editor",
@@ -52,12 +48,12 @@ export default Component.extend({
@discourseComputed("wizardFields")
wizardFieldList(wizardFields) {
- return wizardFields.map((f) => ` w{${f.id}}`);
+ return (wizardFields || []).map((f) => ` w{${f.id}}`);
},
@discourseComputed("wizardActions")
wizardActionList(wizardActions) {
- return wizardActions.map((a) => ` w{${a.id}}`);
+ return (wizardActions || []).map((a) => ` w{${a.id}}`);
},
actions: {
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 e6b0ad04..c9a80e0e 100644
--- a/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6
+++ b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6
@@ -36,7 +36,8 @@ export default Controller.extend({
@discourseComputed("wizard.id")
wizardUrl(wizardId) {
- return window.location.origin + "/w/" + dasherize(wizardId);
+ let baseUrl = window.location.href.split("/admin");
+ return baseUrl[0] + "/w/" + dasherize(wizardId);
},
@discourseComputed("wizard.after_time_scheduled")
diff --git a/assets/javascripts/discourse/templates/components/custom-wizard-field-tag.hbs b/assets/javascripts/discourse/templates/components/custom-wizard-field-tag.hbs
index fb45db4e..90679ae7 100644
--- a/assets/javascripts/discourse/templates/components/custom-wizard-field-tag.hbs
+++ b/assets/javascripts/discourse/templates/components/custom-wizard-field-tag.hbs
@@ -5,4 +5,5 @@
everyTag=true
options=(hash
maximum=field.limit
+ allowAny=field.can_create_tag
)}}
diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs
index 6e524fe3..6273f9a9 100644
--- a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs
+++ b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs
@@ -222,6 +222,18 @@
}}
+
+
+
+
+
+
+
+ {{input
+ type="checkbox"
+ checked=field.can_create_tag}}
+
+
{{/if}}
{{#wizard-subscription-container}}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 267f099f..b3adf8d4 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -16,7 +16,7 @@ en:
x_characters:
one: "%{count} Character"
other: "%{count} Characters"
- quit: "Maybe Later"
+ quit: "Exit"
done_custom: "Done"
back: "Back"
next: "Next"
@@ -277,6 +277,7 @@ en:
prefill: "Prefill"
content: "Content"
tag_groups: "Tag Groups"
+ can_create_tag: "Can Create Tag"
date_time_format:
label: "Format"
instructions: "Moment.js format"
diff --git a/lefthook.yml b/lefthook.yml
index 995d1f2a..91d2ad53 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -20,9 +20,6 @@ pre-commit:
glob: "*.js"
include: "app/assets/javascripts|plugins/.+?/assets/javascripts"
run: yarn eslint -f compact --quiet {staged_files}
- i18n-lint:
- glob: "**/{client,server}.en.yml"
- run: bundle exec ruby script/i18n_lint.rb {staged_files}
lints:
parallel: true
@@ -36,6 +33,3 @@ lints:
run: yarn prettier --list-different **/*.scss
eslint:
run: yarn eslint -f compact --quiet --ext .js .
- i18n-lint:
- glob: "**/{client,server}.en.yml"
- run: bundle exec ruby script/i18n_lint.rb {all_files}
diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb
index 251ec1e5..3b12ad27 100644
--- a/lib/custom_wizard/builder.rb
+++ b/lib/custom_wizard/builder.rb
@@ -135,6 +135,10 @@ class CustomWizard::Builder
params[:limit] = field_template['limit']
end
+ if field_template['type'] === 'tag'
+ params[:can_create_tag] = standardise_boolean(field_template['can_create_tag'])
+ end
+
if field_template['type'] === 'category'
params[:property] = field_template['property']
end
diff --git a/lib/custom_wizard/field.rb b/lib/custom_wizard/field.rb
index 600f685e..6215fc8c 100644
--- a/lib/custom_wizard/field.rb
+++ b/lib/custom_wizard/field.rb
@@ -22,6 +22,7 @@ class CustomWizard::Field
:property,
:content,
:tag_groups,
+ :can_create_tag,
:preview_template,
:placeholder
@@ -47,6 +48,7 @@ class CustomWizard::Field
@property = attrs[:property]
@content = attrs[:content]
@tag_groups = attrs[:tag_groups]
+ @can_create_tag = attrs[:can_create_tag]
@preview_template = attrs[:preview_template]
@placeholder = attrs[:placeholder]
end
@@ -113,7 +115,8 @@ class CustomWizard::Field
limit: nil,
prefill: nil,
content: nil,
- tag_groups: nil
+ tag_groups: nil,
+ can_create_tag: false
},
category: {
limit: 1,
diff --git a/lib/custom_wizard/mapper.rb b/lib/custom_wizard/mapper.rb
index aa444de1..b677a710 100644
--- a/lib/custom_wizard/mapper.rb
+++ b/lib/custom_wizard/mapper.rb
@@ -211,6 +211,8 @@ class CustomWizard::Mapper
user.send(value)
elsif USER_OPTION_FIELDS.include?(value)
user.user_option.send(value)
+ elsif value.include?('avatar')
+ get_avatar_url(value)
else
nil
end
@@ -269,4 +271,15 @@ class CustomWizard::Mapper
def bool(value)
ActiveRecord::Type::Boolean.new.cast(value)
end
+
+ def get_avatar_url(value)
+ parts = value.split('.')
+ valid_sizes = Discourse.avatar_sizes.to_a
+
+ if value === 'avatar' || parts.size === 1 || valid_sizes.exclude?(parts.last.to_i)
+ user.small_avatar_url
+ else
+ user.avatar_template_url.gsub("{size}", parts.last)
+ end
+ end
end
diff --git a/plugin.rb b/plugin.rb
index 51774b64..73701d84 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# name: discourse-custom-wizard
# about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more.
-# version: 2.0.7
+# version: 2.1.3
# authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever
# url: https://github.com/paviliondev/discourse-custom-wizard
# contact_emails: development@pavilion.tech
diff --git a/spec/components/custom_wizard/mapper_spec.rb b/spec/components/custom_wizard/mapper_spec.rb
index 111558a4..56778a07 100644
--- a/spec/components/custom_wizard/mapper_spec.rb
+++ b/spec/components/custom_wizard/mapper_spec.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: true
+# rubocop:disable Style/FrozenStringLiteralComment
describe CustomWizard::Mapper do
fab!(:user1) {
@@ -254,6 +254,36 @@ describe CustomWizard::Mapper do
user: user1
).perform).to eq("Time: #{Time.now.strftime("%B %-d, %Y")}")
end
+
+ it "avatar" do
+ expect(CustomWizard::Mapper.new(
+ inputs: inputs['interpolate_avatar'],
+ data: data,
+ user: user1
+ ).perform).to eq("Avatar: ![avatar](#{user1.small_avatar_url})")
+ end
+
+ it "avatar with invalid size" do
+ avatar_inputs = inputs['interpolate_avatar'].dup
+ avatar_inputs[0]["output"] = "Avatar: ![avatar](u{avatar.345})"
+
+ expect(CustomWizard::Mapper.new(
+ inputs: avatar_inputs,
+ data: data,
+ user: user1
+ ).perform).to eq("Avatar: ![avatar](#{user1.small_avatar_url})")
+ end
+
+ it "avatar with valid size" do
+ avatar_inputs = inputs['interpolate_avatar'].dup
+ avatar_inputs[0]["output"] = "Avatar: ![avatar](u{avatar.120})"
+
+ expect(CustomWizard::Mapper.new(
+ inputs: avatar_inputs,
+ data: data,
+ user: user1
+ ).perform).to eq("Avatar: ![avatar](#{user1.avatar_template_url.gsub("{size}", "120")})")
+ end
end
it "handles greater than pairs" do
diff --git a/spec/fixtures/mapper/inputs.json b/spec/fixtures/mapper/inputs.json
index 443f186b..3fd406a4 100644
--- a/spec/fixtures/mapper/inputs.json
+++ b/spec/fixtures/mapper/inputs.json
@@ -89,6 +89,14 @@
"output": "Time: v{time}"
}
],
+ "interpolate_avatar": [
+ {
+ "type": "assignment",
+ "output_type": "text",
+ "output_connector": "set",
+ "output": "Avatar: ![avatar](u{avatar})"
+ }
+ ],
"validation": [
{
"type": "validation",