Allow users to delete their own diary entries

Fixes #4175
This commit is contained in:
Tom Hughes 2024-02-25 11:02:15 +00:00
parent cf9831c0af
commit 11a59aadfb
8 changed files with 47 additions and 18 deletions

View file

@ -41,7 +41,7 @@ class Ability
can :create, :account_pd_declaration can :create, :account_pd_declaration
can :read, :dashboard can :read, :dashboard
can [:create, :subscribe, :unsubscribe], DiaryEntry can [:create, :subscribe, :unsubscribe], DiaryEntry
can :update, DiaryEntry, :user => user can [:update, :hide, :unhide], DiaryEntry, :user => user
can [:create], DiaryComment can [:create], DiaryComment
can [:show, :create, :destroy], Follow can [:show, :create, :destroy], Follow
can [:read, :create, :destroy], Message can [:read, :create, :destroy], Message

View file

@ -298,7 +298,7 @@ class ApplicationController < ActionController::Base
Ability.new(current_user) Ability.new(current_user)
end end
def deny_access(_exception) def deny_access(_exception = nil)
if current_user if current_user
set_locale set_locale
respond_to do |format| respond_to do |format|

View file

@ -55,7 +55,7 @@ class DiaryEntriesController < ApplicationController
end end
end end
entries = entries.visible unless can? :unhide, DiaryEntry entries = entries.visible_to(current_user)
@params = params.permit(:display_name, :friends, :nearby, :language) @params = params.permit(:display_name, :friends, :nearby, :language)
@ -65,8 +65,7 @@ class DiaryEntriesController < ApplicationController
end end
def show def show
entries = @user.diary_entries entries = @user.diary_entries.visible_to(current_user)
entries = entries.visible unless can? :unhide, DiaryEntry
@entry = entries.find_by(:id => params[:id]) @entry = entries.find_by(:id => params[:id])
if @entry if @entry
@title = t ".title", :user => params[:display_name], :title => @entry.title @title = t ".title", :user => params[:display_name], :title => @entry.title
@ -204,14 +203,24 @@ class DiaryEntriesController < ApplicationController
def hide def hide
entry = DiaryEntry.find(params[:id]) entry = DiaryEntry.find(params[:id])
entry.update(:visible => false)
redirect_to :action => "index", :display_name => entry.user.display_name if can?(:hide, entry)
entry.update(:visible => false)
redirect_to :action => "index", :display_name => entry.user.display_name
else
deny_access
end
end end
def unhide def unhide
entry = DiaryEntry.find(params[:id]) entry = DiaryEntry.find(params[:id])
entry.update(:visible => true)
redirect_to :action => "index", :display_name => entry.user.display_name if can?(:unhide, entry)
entry.update(:visible => true)
redirect_to :action => "index", :display_name => entry.user.display_name
else
deny_access
end
end end
private private

View file

@ -36,6 +36,7 @@ class DiaryEntry < ApplicationRecord
has_many :subscribers, :through => :subscriptions, :source => :user has_many :subscribers, :through => :subscriptions, :source => :user
scope :visible, -> { where(:visible => true) } scope :visible, -> { where(:visible => true) }
scope :visible_to, ->(user) { where(:visible => true).or(where(:user => user)) unless user&.moderator? || user&.administrator? }
validates :title, :presence => true, :length => 1..255, :characters => true validates :title, :presence => true, :length => 1..255, :characters => true
validates :body, :presence => true, :characters => true validates :body, :presence => true, :characters => true

View file

@ -33,12 +33,12 @@
</li> </li>
<% end %> <% end %>
<% if can? :hide, DiaryEntry %> <% if can? :hide, diary_entry %>
<li> <li>
<% if diary_entry.visible %> <% if diary_entry.visible %>
<%= link_to t(".hide_link"), hide_diary_entry_path(diary_entry.user, diary_entry), :method => :post, :data => { :confirm => t(".confirm") } %> <%= link_to t(".delete_link"), hide_diary_entry_path(diary_entry.user, diary_entry), :method => :post, :data => { :confirm => t(".confirm") } %>
<% else %> <% else %>
<%= link_to t(".unhide_link"), unhide_diary_entry_path(diary_entry.user, diary_entry), :method => :post, :data => { :confirm => t(".confirm") } %> <%= link_to t(".restore_link"), unhide_diary_entry_path(diary_entry.user, diary_entry), :method => :post, :data => { :confirm => t(".confirm") } %>
<% end %> <% end %>
</li> </li>
<% end %> <% end %>

View file

@ -606,8 +606,8 @@ en:
other: "%{count} comments" other: "%{count} comments"
no_comments: No comments no_comments: No comments
edit_link: Edit this entry edit_link: Edit this entry
hide_link: Hide this entry delete_link: Delete this entry
unhide_link: Unhide this entry restore_link: Restore this entry
confirm: Confirm confirm: Confirm
report: Report this entry report: Report this entry
diary_comment: diary_comment:

View file

@ -55,7 +55,7 @@ class UserAbilityTest < AbilityTest
test "Diary permissions" do test "Diary permissions" do
ability = Ability.new create(:user) ability = Ability.new create(:user)
[:index, :rss, :show, :create, :edit, :subscribe, :unsubscribe].each do |action| [:index, :rss, :show, :create, :edit, :subscribe, :unsubscribe, :hide, :unhide].each do |action|
assert ability.can?(action, DiaryEntry), "should be able to #{action} DiaryEntries" assert ability.can?(action, DiaryEntry), "should be able to #{action} DiaryEntries"
end end
@ -64,7 +64,6 @@ class UserAbilityTest < AbilityTest
end end
[:hide, :unhide].each do |action| [:hide, :unhide].each do |action|
assert ability.cannot?(action, DiaryEntry), "should not be able to #{action} DiaryEntries"
assert ability.cannot?(action, DiaryComment), "should not be able to #{action} DiaryComment" assert ability.cannot?(action, DiaryComment), "should not be able to #{action} DiaryComment"
end end

View file

@ -792,11 +792,21 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
assert DiaryEntry.find(diary_entry.id).visible assert DiaryEntry.find(diary_entry.id).visible
# Now try as a normal user # Now try as a normal user
session_for(user) session_for(create(:user))
post hide_diary_entry_path(user, diary_entry) post hide_diary_entry_path(user, diary_entry)
assert_redirected_to :controller => :errors, :action => :forbidden assert_redirected_to :controller => :errors, :action => :forbidden
assert DiaryEntry.find(diary_entry.id).visible assert DiaryEntry.find(diary_entry.id).visible
# Now try as the author
session_for(user)
post hide_diary_entry_path(:display_name => user.display_name, :id => diary_entry)
assert_response :redirect
assert_redirected_to :action => :index, :display_name => user.display_name
assert_not DiaryEntry.find(diary_entry.id).visible
# Reset
diary_entry.reload.update(:visible => true)
# Now try as a moderator # Now try as a moderator
session_for(create(:moderator_user)) session_for(create(:moderator_user))
post hide_diary_entry_path(user, diary_entry) post hide_diary_entry_path(user, diary_entry)
@ -823,11 +833,21 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
assert_not DiaryEntry.find(diary_entry.id).visible assert_not DiaryEntry.find(diary_entry.id).visible
# Now try as a normal user # Now try as a normal user
session_for(user) session_for(create(:user))
post unhide_diary_entry_path(user, diary_entry) post unhide_diary_entry_path(user, diary_entry)
assert_redirected_to :controller => :errors, :action => :forbidden assert_redirected_to :controller => :errors, :action => :forbidden
assert_not DiaryEntry.find(diary_entry.id).visible assert_not DiaryEntry.find(diary_entry.id).visible
# Now try as the author
session_for(user)
post unhide_diary_entry_path(:display_name => user.display_name, :id => diary_entry)
assert_response :redirect
assert_redirected_to :action => :index, :display_name => user.display_name
assert DiaryEntry.find(diary_entry.id).visible
# Reset
diary_entry.reload.update(:visible => true)
# Now try as a moderator # Now try as a moderator
session_for(create(:moderator_user)) session_for(create(:moderator_user))
post unhide_diary_entry_path(user, diary_entry) post unhide_diary_entry_path(user, diary_entry)