diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 323af4574..9fcf23fd7 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -1,15 +1,13 @@ class TagsController < ApplicationController - before_action :member_only, :only => [:edit, :update] respond_to :html, :xml, :json def edit - @tag = Tag.find(params[:id]) - check_privilege(@tag) + @tag = authorize Tag.find(params[:id]) respond_with(@tag) end def index - @tags = Tag.paginated_search(params, hide_empty: true) + @tags = authorize Tag.paginated_search(params, hide_empty: true) @tags = @tags.includes(:consequent_aliases) if request.format.html? respond_with(@tags) end @@ -27,27 +25,13 @@ class TagsController < ApplicationController end def show - @tag = Tag.find(params[:id]) + @tag = authorize Tag.find(params[:id]) respond_with(@tag) end def update - @tag = Tag.find(params[:id]) - check_privilege(@tag) - @tag.update(tag_params) + @tag = authorize Tag.find(params[:id]) + @tag.update(permitted_attributes(@tag)) respond_with(@tag) end - - private - - def check_privilege(tag) - raise User::PrivilegeError unless tag.editable_by?(CurrentUser.user) - end - - def tag_params - permitted_params = [:category] - permitted_params << :is_locked if CurrentUser.is_moderator? - - params.require(:tag).permit(permitted_params) - end end diff --git a/app/models/tag.rb b/app/models/tag.rb index 2cff2a059..dec0660b2 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -210,7 +210,7 @@ class Tag < ApplicationRecord # next few lines if the category is changed. tag.update_category_cache - if tag.editable_by?(creator) + if Pundit.policy!([creator, nil], tag).can_change_category? tag.update(category: category_id) end end @@ -382,13 +382,6 @@ class Tag < ApplicationRecord cosplay_tags.grep(/\A(.+)_\(cosplay\)\Z/) { "#{TagAlias.to_aliased([$1]).first}_(cosplay)" } + other_tags end - def editable_by?(user) - return true if user.is_admin? - return true if !is_locked? && user.is_builder? && post_count < 1_000 - return true if !is_locked? && user.is_member? && post_count < 50 - return false - end - def posts Post.tag_match(name) end diff --git a/app/policies/tag_policy.rb b/app/policies/tag_policy.rb new file mode 100644 index 000000000..b5a02f2c9 --- /dev/null +++ b/app/policies/tag_policy.rb @@ -0,0 +1,15 @@ +class TagPolicy < ApplicationPolicy + def can_change_category? + user.is_admin? || + (user.is_builder? && !record.is_locked? && record.post_count < 1_000) || + (user.is_member? && !record.is_locked? && record.post_count < 50) + end + + def can_lock? + user.is_moderator? + end + + def permitted_attributes + [(:category if can_change_category?), (:is_locked if can_lock?)].compact + end +end diff --git a/app/views/tags/edit.html.erb b/app/views/tags/edit.html.erb index cec512f65..9f499e755 100644 --- a/app/views/tags/edit.html.erb +++ b/app/views/tags/edit.html.erb @@ -9,7 +9,7 @@ <%= f.input :category, :collection => TagCategory.canonical_mapping.to_a, :include_blank => false %> <% end %> - <% if CurrentUser.is_moderator? %> + <% if policy(@tag).can_lock? %> <%= f.input :is_locked, :collection => [["No", "false"], ["Yes", "true"]], :include_blank => false %> <% end %> diff --git a/app/views/tags/index.html.erb b/app/views/tags/index.html.erb index ad0c67e75..8f2d2f621 100644 --- a/app/views/tags/index.html.erb +++ b/app/views/tags/index.html.erb @@ -16,7 +16,9 @@ <% end %> <% end %> <% t.column column: "control" do |tag| %> - <%= link_to_if tag.editable_by?(CurrentUser.user), "Edit", edit_tag_path(tag) %> | + <% if policy(tag).update? %> + <%= link_to "Edit", edit_tag_path(tag) %> | + <% end %> <%= link_to "History", post_versions_path(search: { changed_tags: tag.name }) %> | <%= link_to "Related", related_tag_path(search: { query: tag.name }) %> | <%= link_to "Similar", tags_path(search: { fuzzy_name_matches: tag.name, order: :similarity }) %> diff --git a/test/functional/tags_controller_test.rb b/test/functional/tags_controller_test.rb index b555957ba..dac410f5c 100644 --- a/test/functional/tags_controller_test.rb +++ b/test/functional/tags_controller_test.rb @@ -86,6 +86,7 @@ class TagsControllerTest < ActionDispatch::IntegrationTest should "not lock the tag for a user" do put_auth tag_path(@tag), @user, params: {tag: { is_locked: true }} + assert_response 403 assert_equal(false, @tag.reload.is_locked) end @@ -100,6 +101,7 @@ class TagsControllerTest < ActionDispatch::IntegrationTest @member = create(:member_user) put_auth tag_path(@tag), @member, params: {tag: { category: Tag.categories.general }} + assert_response 403 assert_not_equal(Tag.categories.general, @tag.reload.category) end