aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/controllers/api_controller.rb88
-rw-r--r--app/models/info_request.rb10
-rw-r--r--spec/controllers/api_controller_spec.rb22
3 files changed, 59 insertions, 61 deletions
diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb
index 355584288..6c0788d49 100644
--- a/app/controllers/api_controller.rb
+++ b/app/controllers/api_controller.rb
@@ -1,5 +1,9 @@
class ApiController < ApplicationController
before_filter :check_api_key
+ before_filter :check_external_request,
+ :only => [:add_correspondence, :update_state]
+ before_filter :check_request_ownership,
+ :only => [:add_correspondence, :update_state]
def show_request
@request = InfoRequest.find(params[:id])
@@ -77,12 +81,6 @@ class ApiController < ApplicationController
end
def add_correspondence
- request = InfoRequest.find_by_id(params[:id])
- if request.nil?
- render :json => { "errors" => ["Could not find request #{params[:id]}"] }, :status => 404
- return
- end
-
json = ActiveSupport::JSON.decode(params[:correspondence_json])
attachments = params[:attachments]
@@ -93,16 +91,6 @@ class ApiController < ApplicationController
errors = []
- if !request.is_external?
- render :json => { "errors" => ["Request #{params[:id]} cannot be updated using the API"] }, :status => 500
- return
- end
-
- if request.public_body_id != @public_body.id
- render :json => { "errors" => ["You do not own request #{params[:id]}"] }, :status => 500
- return
- end
-
if !["request", "response"].include?(direction)
errors << "The direction parameter must be 'request' or 'response'"
end
@@ -126,16 +114,16 @@ class ApiController < ApplicationController
# In the 'request' direction, i.e. what we (Alaveteli) regard as outgoing
outgoing_message = OutgoingMessage.new(
- :info_request => request,
+ :info_request => @request,
:status => 'ready',
:message_type => 'followup',
:body => body,
:last_sent_at => sent_at,
:what_doing => 'normal_sort'
)
- request.outgoing_messages << outgoing_message
- request.save!
- request.log_event("followup_sent",
+ @request.outgoing_messages << outgoing_message
+ @request.save!
+ @request.log_event("followup_sent",
:api => true,
:email => nil,
:outgoing_message_id => outgoing_message.id,
@@ -155,50 +143,33 @@ class ApiController < ApplicationController
)
end
- mail = RequestMailer.external_response(request, body, sent_at, attachment_hashes)
+ mail = RequestMailer.external_response(@request, body, sent_at, attachment_hashes)
- request.receive(mail, mail.encoded, true)
+ @request.receive(mail, mail.encoded, true)
if new_state && InfoRequest.enumerate_states.include?(new_state)
- request.set_described_state(new_state)
+ @request.set_described_state(new_state)
end
end
render :json => {
- 'url' => make_url("request", request.url_title),
+ 'url' => make_url("request", @request.url_title),
}
end
def update_state
- request = InfoRequest.find_by_id(params[:id])
- if request.nil?
- render :json => {
- "errors" => ["Could not find request #{params[:id]}"]
- },
- :status => 404
- return
- end
new_state = params["state"]
errors = []
- if !request.is_external?
- render :json => {
- "errors" => ["Request #{params[:id]} cannot be updated using the API"]
- },
- :status => 500
- return
- end
-
- if request.public_body_id != @public_body.id
- render :json => {
- "errors" => ["You do not own request #{params[:id]}"]
- },
- :status => 500
- return
- end
-
- if InfoRequest.enumerate_states.include?(new_state)
- request.set_described_state(new_state)
+ if InfoRequest.allowed_incoming_states.include?(new_state)
+ ActiveRecord::Base.transaction do
+ event = @request.log_event("status_update",
+ { :script => "#{@public_body.name} on behalf of requester via API",
+ :old_described_state => @request.described_state,
+ :described_state => new_state,
+ })
+ @request.set_described_state(new_state)
+ end
else
render :json => {
"errors" => ["'#{new_state}' is not a valid request state" ]
@@ -208,7 +179,7 @@ class ApiController < ApplicationController
end
render :json => {
- 'url' => make_url("request", request.url_title),
+ 'url' => make_url("request", @request.url_title),
}
end
@@ -295,6 +266,21 @@ class ApiController < ApplicationController
raise PermissionDenied if @public_body.nil?
end
+ def check_external_request
+ @request = InfoRequest.find_by_id(params[:id])
+ if @request.nil?
+ render :json => { "errors" => ["Could not find request #{params[:id]}"] }, :status => 404
+ elsif !@request.is_external?
+ render :json => { "errors" => ["Request #{params[:id]} cannot be updated using the API"] }, :status => 403
+ end
+ end
+
+ def check_request_ownership
+ if @request.public_body_id != @public_body.id
+ render :json => { "errors" => ["You do not own request #{params[:id]}"] }, :status => 403
+ end
+ end
+
private
def make_url(*args)
"http://" + AlaveteliConfiguration::domain + "/" + args.join("/")
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index a2112a210..aed651ad3 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -115,6 +115,16 @@ class InfoRequest < ActiveRecord::Base
states
end
+ # Subset of states accepted via the API
+ def self.allowed_incoming_states
+ [
+ 'waiting_response',
+ 'rejected',
+ 'successful',
+ 'partially_successful'
+ ]
+ end
+
# Possible reasons that a request could be reported for administrator attention
def report_reasons
[_("Contains defamatory material"),
diff --git a/spec/controllers/api_controller_spec.rb b/spec/controllers/api_controller_spec.rb
index 07c2ca6e0..b6023089a 100644
--- a/spec/controllers/api_controller_spec.rb
+++ b/spec/controllers/api_controller_spec.rb
@@ -225,7 +225,7 @@ describe ApiController, "when using the API" do
"body" => "xxx"
}.to_json
- response.status.should == 500
+ response.status.should == 403
ActiveSupport::JSON.decode(response.body)["errors"].should == [
"Request #{request_id} cannot be updated using the API"]
@@ -247,7 +247,7 @@ describe ApiController, "when using the API" do
"body" => "xxx"
}.to_json
- response.status.should == 500
+ response.status.should == 403
ActiveSupport::JSON.decode(response.body)["errors"].should == [
"You do not own request #{request_id}"]
@@ -256,7 +256,8 @@ describe ApiController, "when using the API" do
end
it "should return a JSON 404 error for non-existent requests" do
- request_id = 123459876 # Let's hope this doesn't exist!
+ request_id = "123459876"
+ InfoRequest.stub(:find_by_id).with(request_id).and_return(nil)
sent_at = "2012-05-28T12:35:39+01:00"
response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n"
post :add_correspondence,
@@ -271,7 +272,7 @@ describe ApiController, "when using the API" do
ActiveSupport::JSON.decode(response.body)["errors"].should == ["Could not find request 123459876"]
end
- it "should return a JSON 500 error if we try to add correspondence to a request we don't own" do
+ it "should return a JSON 403 error if we try to add correspondence to a request we don't own" do
request_id = info_requests(:naughty_chicken_request).id
sent_at = "2012-05-28T12:35:39+01:00"
response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n"
@@ -283,7 +284,7 @@ describe ApiController, "when using the API" do
"sent_at" => sent_at,
"body" => response_body
}.to_json
- response.status.should == 500
+ response.status.should == 403
ActiveSupport::JSON.decode(response.body)["errors"].should == ["Request #{request_id} cannot be updated using the API"]
end
@@ -360,11 +361,11 @@ describe ApiController, "when using the API" do
post :update_state,
:k => public_bodies(:geraldine_public_body).api_key,
:id => request_id,
- :state => "not_held"
+ :state => "partially_successful"
# It should have updated the status
request = InfoRequest.find_by_id(request_id)
- request.described_state.should == "not_held"
+ request.described_state.should == "partially_successful"
end
it "should return a JSON 500 error if an invalid state is sent" do
@@ -391,7 +392,8 @@ describe ApiController, "when using the API" do
end
it "should return a JSON 404 error for non-existent requests" do
- request_id = 123459876 # Let's hope this doesn't exist!
+ request_id = "123459876"
+ InfoRequest.stub(:find_by_id).with(request_id).and_return(nil)
post :update_state,
:k => public_bodies(:geraldine_public_body).api_key,
@@ -402,7 +404,7 @@ describe ApiController, "when using the API" do
ActiveSupport::JSON.decode(response.body)["errors"].should == ["Could not find request 123459876"]
end
- it "should return a JSON 500 error if we try to add correspondence to a request we don't own" do
+ it "should return a JSON 403 error if we try to add correspondence to a request we don't own" do
request_id = info_requests(:naughty_chicken_request).id
post :update_state,
@@ -410,7 +412,7 @@ describe ApiController, "when using the API" do
:id => request_id,
:state => "successful"
- response.status.should == 500
+ response.status.should == 403
ActiveSupport::JSON.decode(response.body)["errors"].should == ["Request #{request_id} cannot be updated using the API"]
end
end