diff --git a/app/controllers/response_templates_controller.rb b/app/controllers/response_templates_controller.rb
index 826474afa..60f6ffc15 100644
--- a/app/controllers/response_templates_controller.rb
+++ b/app/controllers/response_templates_controller.rb
@@ -31,9 +31,12 @@ class ResponseTemplatesController < ApplicationController
def create
authorize ResponseTemplate
- response_template.user_id = current_user.id
+
+ unless tries_to_create_a_mod_response_template? && can_create_mod_response_templates?
+ response_template.user_id = current_user.id
+ response_template.type_of = "personal_comment"
+ end
response_template.content_type = "body_markdown"
- response_template.type_of = "personal_comment"
if response_template.save
flash[:settings_notice] =
@@ -87,6 +90,18 @@ class ResponseTemplatesController < ApplicationController
private
+ def authorized_user
+ @authorized_user ||= Authorizer.for(user: current_user)
+ end
+
+ def can_create_mod_response_templates?
+ authorized_user.accesses_mod_response_templates?
+ end
+
+ def tries_to_create_a_mod_response_template?
+ params[:response_template][:type_of] == "mod_comment"
+ end
+
def response_template
@response_template ||= if params[:id].present?
ResponseTemplate.find(params[:id])
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 4b35593bc..d4495ea8e 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -218,8 +218,6 @@ class UsersController < ApplicationController
def signout_confirm; end
def handle_settings_tab
- return @tab = "profile" if @tab.blank?
-
case @tab
when "profile"
handle_integrations_tab
@@ -302,8 +300,10 @@ class UsersController < ApplicationController
end
def handle_response_templates_tab
- @response_templates = current_user.response_templates
- @response_template = ResponseTemplate.find_or_initialize_by(id: params[:id], user: current_user)
+ @personal_response_templates = current_user.response_templates
+ @trusted_response_templates = policy_scope(ResponseTemplate).where(type_of: "mod_comment")
+ @response_template = policy_scope(ResponseTemplate).find_by(id: params[:id]) ||
+ ResponseTemplate.new
end
def set_user
diff --git a/app/policies/authorizer.rb b/app/policies/authorizer.rb
index 7ad3ee3ef..9d987974c 100644
--- a/app/policies/authorizer.rb
+++ b/app/policies/authorizer.rb
@@ -75,6 +75,10 @@ module Authorizer
has_role?(:creator)
end
+ def accesses_mod_response_templates?
+ has_trusted_role? || any_admin? || moderator? || tag_moderator?
+ end
+
# When you need to know if we trust the user, but don't want to
# have stale information that the `trusted?` method might give
# you.
diff --git a/app/policies/response_template_policy.rb b/app/policies/response_template_policy.rb
index 65e3222f1..d10711ed7 100644
--- a/app/policies/response_template_policy.rb
+++ b/app/policies/response_template_policy.rb
@@ -3,8 +3,8 @@ class ResponseTemplatePolicy < ApplicationPolicy
class Scope < Scope
def resolve
- if user.has_trusted_role? || user.any_admin? || user.moderator? || user.tag_moderator?
- scope.where(user: user, type_of: "personal_comment") + scope.where.not(type_of: "personal_comment")
+ if Authorizer.for(user: user).accesses_mod_response_templates?
+ scope.where(user: user, type_of: "personal_comment").or(scope.where.not(type_of: "personal_comment"))
else
scope.where(user: user, type_of: "personal_comment")
end
@@ -30,14 +30,21 @@ class ResponseTemplatePolicy < ApplicationPolicy
user_moderator? && mod_comment?
end
- def destroy?
+ def modify?
+ return true if mod_comment? && user_trusted?
+
user_owner?
end
- alias update? destroy?
+ alias update? modify?
+ alias destroy? modify?
def permitted_attributes_for_create
- PERMITTED_ATTRIBUTES
+ if user_trusted?
+ PERMITTED_ATTRIBUTES + [:type_of]
+ else
+ PERMITTED_ATTRIBUTES
+ end
end
def permitted_attributes_for_update
@@ -50,6 +57,10 @@ class ResponseTemplatePolicy < ApplicationPolicy
user.id == record.user_id
end
+ def user_trusted?
+ Authorizer.for(user: user).accesses_mod_response_templates?
+ end
+
def user_moderator?
user_any_admin? || user.moderator_for_tags&.present?
end
diff --git a/app/views/users/_response_template.html.erb b/app/views/users/_response_template.html.erb
new file mode 100644
index 000000000..61e7e52c2
--- /dev/null
+++ b/app/views/users/_response_template.html.erb
@@ -0,0 +1,13 @@
+
mb-4">
+
+
+ <%= response_template.title %>
+
+
+ <%= form_with url: response_template_path(response_template.id), method: :delete, local: true, html: { onsubmit: "return confirm('#{t('views.settings.extensions.comment.confirm', template: response_template.title)}');" } do %>
+
+ <% end %>
+
<%= t("views.settings.extensions.comment.edit") %>
+
+
+
diff --git a/app/views/users/_response_templates.html.erb b/app/views/users/_response_templates.html.erb
index 7e9da0fc5..8a4362b52 100644
--- a/app/views/users/_response_templates.html.erb
+++ b/app/views/users/_response_templates.html.erb
@@ -7,28 +7,23 @@
- <% if @response_templates.present? %>
+ <% if @personal_response_templates.present? %>
<%= t("views.settings.extensions.comment.saved") %>
- <% @response_templates.each do |response_template| %>
- mb-4">
-
-
- <%= response_template.title %>
-
-
- <%= form_with url: response_template_path(response_template.id), method: :delete, local: true, html: { onsubmit: "return confirm('#{t('views.settings.extensions.comment.confirm', template: response_template.title)}');" } do %>
-
- <% end %>
-
<%= t("views.settings.extensions.comment.edit") %>
-
-
-
- <% end %>
-
- <% end %>
+ <%= render partial: "response_template", collection: @personal_response_templates %>
+
+ <% end %>
+
+ <% if @trusted_response_templates.present? %>
+
+
+ <%= t("views.settings.extensions.comment.trusted") %>
+
+ <%= render partial: "response_template", collection: @trusted_response_templates %>
+
+ <% end %>
<%= form_with model: @response_template do |f| %>
@@ -60,6 +55,22 @@
<%= f.text_area :content, value: content, class: "crayons-textfield" %>
+ <% if current_user.has_trusted_role? && @response_template.new_record? %>
+
+
+
+ <% end %>
+
diff --git a/config/locales/views/settings/en.yml b/config/locales/views/settings/en.yml
index 9fe54d522..599857073 100644
--- a/config/locales/views/settings/en.yml
+++ b/config/locales/views/settings/en.yml
@@ -130,6 +130,7 @@ en:
remove: Remove
save: Save template
saved: Saved templates
+ trusted: Trusted user templates
github:
heading: GitHub
desc1: Pin your GitHub repositories to your profile.
diff --git a/spec/policies/response_template_policy_spec.rb b/spec/policies/response_template_policy_spec.rb
index 7c2c0c230..9711d889b 100644
--- a/spec/policies/response_template_policy_spec.rb
+++ b/spec/policies/response_template_policy_spec.rb
@@ -39,15 +39,14 @@ RSpec.describe ResponseTemplatePolicy, type: :policy do
let(:user) { create(:user, :tag_moderator) }
let(:response_template) { create(:response_template, type_of: "mod_comment", user: nil) }
- it { is_expected.to permit_actions(%i[moderator_index create moderator_create]) }
- it { is_expected.to forbid_actions(%i[update destroy admin_index]) }
+ it { is_expected.to permit_actions(%i[moderator_index create moderator_create update destroy]) }
+ it { is_expected.to forbid_actions(%i[admin_index]) }
end
context "when user is an admin" do
let(:user) { create(:user, :admin) }
let(:response_template) { create(:response_template, type_of: "mod_comment", user: nil) }
- it { is_expected.to permit_actions(%i[moderator_index create moderator_create admin_index]) }
- it { is_expected.to forbid_actions(%i[update destroy]) }
+ it { is_expected.to permit_actions(%i[moderator_index create moderator_create admin_index update destroy]) }
end
end
diff --git a/spec/requests/response_templates_spec.rb b/spec/requests/response_templates_spec.rb
index 1e710d753..e4842cd20 100644
--- a/spec/requests/response_templates_spec.rb
+++ b/spec/requests/response_templates_spec.rb
@@ -2,6 +2,7 @@ require "rails_helper"
RSpec.describe "ResponseTemplate", type: :request do
let(:user) { create(:user) }
+ let(:trusted_user) { create(:user, :trusted) }
let(:moderator) { create(:user, :tag_moderator) }
let(:admin) { create(:user, :admin) }
@@ -30,7 +31,6 @@ RSpec.describe "ResponseTemplate", type: :request do
headers = { HTTP_ACCEPT: "application/json" }
get response_templates_path, params: { type_of: "personal_comment" }, headers: headers
-
expect(response.parsed_body.class).to eq Array
expect(response.parsed_body.length).to eq total_response_templates
end
@@ -120,65 +120,155 @@ RSpec.describe "ResponseTemplate", type: :request do
end
describe "POST /response_templates #create" do
- before { sign_in user }
+ context "when signed in as normal user" do
+ before { sign_in user }
- let(:attributes) do
- {
- title: "some_title",
- content: "some content",
- type_of: "personal_comment"
- }
+ let(:attributes) do
+ {
+ title: "some_title",
+ content: "some content",
+ type_of: "personal_comment"
+ }
+ end
+
+ it "successfully creates the proper response template" do
+ post response_templates_path, params: {
+ response_template: {
+ title: attributes[:title],
+ content: attributes[:content]
+ }
+ }
+
+ response_template = ResponseTemplate.last
+ expect(response_template.user_id).to eq user.id
+ expect(response_template.title).to eq attributes[:title]
+ expect(response_template.content).to eq attributes[:content]
+ expect(response_template.type_of).to eq attributes[:type_of]
+ end
+
+ it "can only create personal response templates" do
+ post response_templates_path, params: {
+ response_template: {
+ title: attributes[:title],
+ content: attributes[:content],
+ type_of: "mod_comment"
+ }
+ }
+
+ response_template = ResponseTemplate.last
+ expect(response_template.type_of).to eq "personal_comment"
+ end
+
+ it "redirects to the edit page upon success" do
+ post response_templates_path, params: {
+ response_template: {
+ title: attributes[:title],
+ content: attributes[:content]
+ }
+ }
+ expect(response.redirect_url).to include user_settings_path(tab: "response-templates",
+ id: ResponseTemplate.last.id)
+ end
end
- it "successfully creates the proper response template" do
- post response_templates_path, params: {
- response_template: {
- title: attributes[:title],
- content: attributes[:content]
- }
- }
+ context "when signed in as trusted user" do
+ before { sign_in trusted_user }
- response_template = ResponseTemplate.last
- expect(response_template.user_id).to eq user.id
- expect(response_template.title).to eq attributes[:title]
- expect(response_template.content).to eq attributes[:content]
- expect(response_template.type_of).to eq attributes[:type_of]
- end
-
- it "redirects to the edit page upon success" do
- post response_templates_path, params: {
- response_template: {
- title: attributes[:title],
- content: attributes[:content]
+ let(:attributes) do
+ {
+ title: "some_title",
+ content: "some content",
+ type_of: "mod_comment"
}
- }
- expect(response.redirect_url).to include user_settings_path(tab: "response-templates",
- id: ResponseTemplate.last.id)
+ end
+
+ it "successfully creates a personal response template" do
+ post response_templates_path, params: {
+ response_template: {
+ title: attributes[:title],
+ content: attributes[:content]
+ }
+ }
+
+ response_template = ResponseTemplate.last
+ expect(response_template.user_id).to eq trusted_user.id
+ expect(response_template.title).to eq attributes[:title]
+ expect(response_template.content).to eq attributes[:content]
+ expect(response_template.type_of).to eq "personal_comment"
+ end
+
+ it "successfully creates a mod_comment response template" do
+ post response_templates_path, params: {
+ response_template: {
+ title: attributes[:title],
+ content: attributes[:content],
+ type_of: attributes[:type_of]
+ }
+ }
+
+ response_template = ResponseTemplate.last
+ expect(response_template.user_id).to be_nil
+ expect(response_template.title).to eq attributes[:title]
+ expect(response_template.content).to eq attributes[:content]
+ expect(response_template.type_of).to eq "mod_comment"
+ end
+
+ it "redirects to the edit page upon success" do
+ post response_templates_path, params: {
+ response_template: {
+ title: attributes[:title],
+ content: attributes[:content]
+ }
+ }
+ expect(response.redirect_url).to include user_settings_path(tab: "response-templates",
+ id: ResponseTemplate.last.id)
+ end
end
end
describe "PATCH /response_templates/:id #update" do
- before { sign_in user }
+ context "when signed-in as normal user updating a personal template" do
+ before { sign_in user }
- let(:response_template) { create(:response_template, user: user) }
+ let(:response_template) { create(:response_template, user: user) }
- it "successfully updates the response template" do
- title = "something else"
- patch response_template_path(response_template.id), params: { response_template: { title: title } }
- expect(ResponseTemplate.first.title).to eq title
+ it "successfully updates the response template" do
+ title = "something else"
+ patch response_template_path(response_template.id), params: { response_template: { title: title } }
+ expect(ResponseTemplate.first.title).to eq title
+ end
+
+ it "redirects back to the response template" do
+ patch response_template_path(response_template.id), params: { response_template: { title: "something else" } }
+ expect(response.redirect_url).to include user_settings_path(tab: "response-templates",
+ id: ResponseTemplate.first.id)
+ end
+
+ it "shows the previously written content on a failed submission" do
+ content = "something something something"
+ patch response_template_path(response_template.id),
+ params: { response_template: { title: "", content: content } }
+ follow_redirect!
+ expect(response.body).to include content
+ end
end
- it "redirects back to the response template" do
- patch response_template_path(response_template.id), params: { response_template: { title: "something else" } }
- expect(response.redirect_url).to include user_settings_path(tab: "response-templates",
- id: ResponseTemplate.first.id)
- end
+ context "when signed-in as trusted user updating a mod_comment template" do
+ before { sign_in trusted_user }
- it "shows the previously written content on a failed submission" do
- content = "something something something"
- patch response_template_path(response_template.id), params: { response_template: { title: "", content: content } }
- follow_redirect!
- expect(response.body).to include content
+ let(:response_template) { create :response_template, user: nil, type_of: "mod_comment" }
+
+ it "successfully updates the response template" do
+ title = "something else"
+ patch response_template_path(response_template.id), params: { response_template: { title: title } }
+ expect(ResponseTemplate.first.title).to eq title
+ end
+
+ it "does not permit changing template type_of" do
+ patch response_template_path(response_template.id),
+ params: { response_template: { type_of: "personal_comment" } }
+ expect(ResponseTemplate.first.type_of).to eq("mod_comment")
+ end
end
end