Skip to content

Commit

Permalink
Merge pull request #624 from alphagov/fix-release-lock
Browse files Browse the repository at this point in the history
Fix a couple of bugs with admin petition locking
  • Loading branch information
pixeltrix authored Sep 12, 2017
2 parents 6d93d48 + e35621d commit 910b393
Show file tree
Hide file tree
Showing 8 changed files with 643 additions and 375 deletions.
9 changes: 7 additions & 2 deletions app/assets/javascripts/edit_lock.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(function ($) {
'use strict';

$.fn.editLock = function(id, user_id, path) {
$.fn.editLock = function(id, user_id, path, moderated) {
var $html = this;
var $message = $html.find('.edit-lock-message');
var $override = $html.find('#edit-lock-override');
Expand All @@ -12,6 +12,7 @@
var PATH = path;
var INTERVAL = 10000;
var LOCK_URL = PATH + '/' + ID + '/lock.json';
var MODERATED = moderated;

var EditLock = {
processStatus: function(data) {
Expand Down Expand Up @@ -59,7 +60,11 @@
},

cancelClicked: function(e) {
window.location = PATH + '/' + ID;
if (MODERATED) {
window.location = PATH + '/' + ID;
} else {
window.history.back();
}
}
};

Expand Down
5 changes: 1 addition & 4 deletions app/models/archived/petition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -326,15 +326,12 @@ def force_checkout!(user, now = Time.current)

def release!(user)
with_lock do
if locked_by.present? && locked_by != user
raise RuntimeError, "Petition already being edited by #{locked_by.pretty_name}"
else
if locked_by.present? && locked_by == user
update!(locked_by: nil, locked_at: nil)
end
end
end


private

def evaluate_debate_state
Expand Down
4 changes: 1 addition & 3 deletions app/models/petition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -691,9 +691,7 @@ def force_checkout!(user, now = Time.current)

def release!(user)
with_lock do
if locked_by.present? && locked_by != user
raise RuntimeError, "Petition already being edited by #{locked_by.pretty_name}"
else
if locked_by.present? && locked_by == user
update!(locked_by: nil, locked_at: nil)
end
end
Expand Down
4 changes: 2 additions & 2 deletions app/views/admin/admin/_edit_lock.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
<script>
$(document).ready(function() {
<% if @petition.is_a?(::Archived::Petition) %>
$("#edit-lock").editLock(<%= @petition.id %>, <%= current_user.id %>, '/admin/archived/petitions');
$("#edit-lock").editLock(<%= @petition.id %>, <%= current_user.id %>, '/admin/archived/petitions', true);
<% else %>
$("#edit-lock").editLock(<%= @petition.id %>, <%= current_user.id %>, '/admin/petitions');
$("#edit-lock").editLock(<%= @petition.id %>, <%= current_user.id %>, '/admin/petitions', <%= @petition.moderated? %>);
<% end %>
});
</script>
8 changes: 6 additions & 2 deletions spec/controllers/admin/archived/locks_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,17 @@
it "doesn't update the locked_by association" do
expect {
get :destroy, petition_id: petition.to_param, format: :json
}.to raise_error(RuntimeError, /Petition already being edited/)
}.not_to change {
petition.reload.locked_by
}
end

it "doesn't update the locked_at timestamp" do
expect {
get :destroy, petition_id: petition.to_param, format: :json
}.to raise_error(RuntimeError, /Petition already being edited/)
}.not_to change {
petition.reload.locked_at
}
end
end
end
Expand Down
8 changes: 6 additions & 2 deletions spec/controllers/admin/locks_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,17 @@
it "doesn't update the locked_by association" do
expect {
get :destroy, petition_id: petition.to_param, format: :json
}.to raise_error(RuntimeError, /Petition already being edited/)
}.not_to change {
petition.reload.locked_by
}
end

it "doesn't update the locked_at timestamp" do
expect {
get :destroy, petition_id: petition.to_param, format: :json
}.to raise_error(RuntimeError, /Petition already being edited/)
}.not_to change {
petition.reload.locked_at
}
end
end
end
Expand Down
250 changes: 250 additions & 0 deletions spec/models/archived/petition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -848,4 +848,254 @@
end
end
end

describe "#update_lock!" do
let(:current_user) { FactoryGirl.create(:moderator_user) }

context "when the petition is not locked" do
let(:petition) { FactoryGirl.create(:petition, locked_by: nil, locked_at: nil) }

it "doesn't update the locked_by association" do
expect {
petition.update_lock!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "doesn't update the locked_at timestamp" do
expect {
petition.update_lock!(current_user)
}.not_to change {
petition.reload.locked_at
}
end
end

context "when the petition is locked by someone else" do
let(:other_user) { FactoryGirl.create(:moderator_user) }
let(:petition) { FactoryGirl.create(:petition, locked_by: other_user, locked_at: 1.hour.ago) }

it "doesn't update the locked_by association" do
expect {
petition.update_lock!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "doesn't update the locked_at timestamp" do
expect {
petition.update_lock!(current_user)
}.not_to change {
petition.reload.locked_at
}
end
end

context "when the petition is locked by the current user" do
let(:petition) { FactoryGirl.create(:petition, locked_by: current_user, locked_at: 1.hour.ago) }

it "doesn't update the locked_by association" do
expect {
petition.update_lock!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "updates the locked_at timestamp" do
expect {
petition.update_lock!(current_user)
}.to change {
petition.reload.locked_at
}.to be_within(1.second).of(Time.current)
end
end
end

describe "#checkout!" do
let(:current_user) { FactoryGirl.create(:moderator_user) }

context "when the petition is not locked" do
let(:petition) { FactoryGirl.create(:petition, locked_by: nil, locked_at: nil) }

it "updates the locked_by association" do
expect {
petition.checkout!(current_user)
}.to change {
petition.reload.locked_by
}.from(nil).to(current_user)
end

it "updates the locked_at timestamp" do
expect {
petition.checkout!(current_user)
}.to change {
petition.reload.locked_at
}.from(nil).to(be_within(1.second).of(Time.current))
end
end

context "when the petition is locked by someone else" do
let(:other_user) { FactoryGirl.create(:moderator_user) }
let(:petition) { FactoryGirl.create(:petition, locked_by: other_user, locked_at: 1.hour.ago) }

it "raises an error" do
expect {
petition.checkout!(current_user)
}.to raise_error(RuntimeError, /Petition already being edited/)
end
end

context "when the petition is locked by the current user" do
let(:petition) { FactoryGirl.create(:petition, locked_by: current_user, locked_at: 1.hour.ago) }

it "doesn't update the locked_by association" do
expect {
petition.checkout!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "updates the locked_at timestamp" do
expect {
petition.checkout!(current_user)
}.to change {
petition.reload.locked_at
}.to be_within(1.second).of(Time.current)
end
end
end

describe "#force_checkout!" do
let(:current_user) { FactoryGirl.create(:moderator_user) }

context "when the petition is not locked" do
let(:petition) { FactoryGirl.create(:petition, locked_by: nil, locked_at: nil) }

it "updates the locked_by association" do
expect {
petition.force_checkout!(current_user)
}.to change {
petition.reload.locked_by
}.from(nil).to(current_user)
end

it "updates the locked_at timestamp" do
expect {
petition.force_checkout!(current_user)
}.to change {
petition.reload.locked_at
}.from(nil).to(be_within(1.second).of(Time.current))
end
end

context "when the petition is locked by someone else" do
let(:other_user) { FactoryGirl.create(:moderator_user) }
let(:petition) { FactoryGirl.create(:petition, locked_by: other_user, locked_at: 1.hour.ago) }

it "updates the locked_by association" do
expect {
petition.force_checkout!(current_user)
}.to change {
petition.reload.locked_by
}.from(other_user).to(current_user)
end

it "updates the locked_at timestamp" do
expect {
petition.force_checkout!(current_user)
}.to change {
petition.reload.locked_at
}.to(be_within(1.second).of(Time.current))
end
end

context "when the petition is locked by the current user" do
let(:petition) { FactoryGirl.create(:petition, locked_by: current_user, locked_at: 1.hour.ago) }

it "doesn't update the locked_by association" do
expect {
petition.force_checkout!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "updates the locked_at timestamp" do
expect {
petition.force_checkout!(current_user)
}.to change {
petition.reload.locked_at
}.to be_within(1.second).of(Time.current)
end
end
end

describe "#release!" do
let(:current_user) { FactoryGirl.create(:moderator_user) }

context "when the petition is not locked" do
let(:petition) { FactoryGirl.create(:petition, locked_by: nil, locked_at: nil) }

it "doesn't update the locked_by association" do
expect {
petition.release!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "doesn't update the locked_at timestamp" do
expect {
petition.release!(current_user)
}.not_to change {
petition.reload.locked_at
}
end
end

context "when the petition is locked by someone else" do
let(:other_user) { FactoryGirl.create(:moderator_user) }
let(:petition) { FactoryGirl.create(:petition, locked_by: other_user, locked_at: 1.hour.ago) }

it "doesn't update the locked_by association" do
expect {
petition.release!(current_user)
}.not_to change {
petition.reload.locked_by
}
end

it "doesn't update the locked_at timestamp" do
expect {
petition.release!(current_user)
}.not_to change {
petition.reload.locked_at
}
end
end

context "when the petition is locked by the current user" do
let(:petition) { FactoryGirl.create(:petition, locked_by: current_user, locked_at: 1.hour.ago) }

it "updates the locked_by association" do
expect {
petition.release!(current_user)
}.to change {
petition.reload.locked_by
}.from(current_user).to(nil)
end

it "updates the locked_at timestamp" do
expect {
petition.release!(current_user)
}.to change {
petition.reload.locked_at
}.to be_nil
end
end
end
end
Loading

0 comments on commit 910b393

Please sign in to comment.