aboutsummaryrefslogtreecommitdiffstats
path: root/app/controllers/api_controller.rb
blob: 9bcd82632a06063fea4789671159828372508d60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
class ApiController < ApplicationController
    before_filter :check_api_key
    
    def show_request
        @request = InfoRequest.find(params[:id])
        raise PermissionDenied if @request.public_body_id != @public_body.id
        
        @request_data = {
            :id => @request.id,
            :url => make_url("request", @request.url_title),
            :title => @request.title,
            
            :created_at => @request.created_at,
            :updated_at => @request.updated_at,
            
            :status => @request.calculate_status,
            
            :public_body_url => make_url("body", @request.public_body.url_name),
            :requestor_url => make_url("user", @request.user.url_name),
            :request_email => @request.incoming_email,
            
            :request_text => @request.last_event_forming_initial_request.outgoing_message.body,
        }
        
        render :json => @request_data
    end
    
    def create_request
        json = ActiveSupport::JSON.decode(params[:request_json])
        request = InfoRequest.new(
            :title => json["title"],
            :public_body_id => @public_body.id,
            :described_state => "waiting_response",
            :external_user_name => json["external_user_name"],
            :external_url => json["external_url"]
        )
        
        outgoing_message = OutgoingMessage.new(
            :status => 'ready',
            :message_type => 'initial_request',
            :body => json["body"],
            :last_sent_at => Time.now(),
            :what_doing => 'normal_sort',
            :info_request => request
        )
        request.outgoing_messages << outgoing_message
        
        # Return an error if the request is invalid
        # (Can this ever happen?)
        if !request.valid?
            render :json => {
                'errors' => request.errors.full_messages
            }
            return
        end
        
        # Save the request, and add the corresponding InfoRequestEvent
        request.save!
        request.log_event("sent",
            :api => true,
            :email => nil,
            :outgoing_message_id => outgoing_message.id,
            :smtp_message_id => nil
        )
        
        # Return the URL and ID number.
        render :json => {
            'url' => make_url("request", request.url_title),
            'id'  => request.id
        }
        
    end
    
    def add_correspondence
        request = InfoRequest.find(params[:id])
        json = ActiveSupport::JSON.decode(params[:correspondence_json])
        
        direction = json["direction"]
        body = json["body"]
        sent_at_str = json["sent_at"]
        
        errors = []
        
        if !request.is_external?
            raise ActiveRecord::RecordNotFound.new("Request #{params[:id]} cannot be updated using the API")
        end
        
        if request.public_body_id != @public_body.id
            raise ActiveRecord::RecordNotFound.new("You do not own request #{params[:id]}")
        end
        
        if !["request", "response"].include?(direction)
            errors << "The direction parameter must be 'request' or 'response'"
        end
        
        if body.nil?
            errors << "The 'body' is missing"
        elsif body.empty?
            errors << "The 'body' is empty"
        end
        
        begin
            sent_at = Time.iso8601(sent_at_str)
        rescue ArgumentError
            errors << "Failed to parse 'sent_at' field as ISO8601 time: #{sent_at_str}"
        end
        
        if !errors.empty?
            render :json => { "errors" => errors }
            return
        end
        
        if direction == "request"
            # In the 'request' direction, i.e. what we (Alaveteli) regard as outgoing
            
            outgoing_message = OutgoingMessage.new(
                :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",
                :api => true,
                :email => nil,
                :outgoing_message_id => outgoing_message.id,
                :smtp_message_id => nil
            )
        else
            # In the 'response' direction, i.e. what we (Alaveteli) regard as incoming
            
            raw_email = RawEmail.new
            incoming_message = IncomingMessage.new(
                :info_request => request,
                :raw_email => raw_email,
                :sent_at => sent_at
            )
            raw_email.incoming_message = incoming_message
            raw_email.save!
            raw_email.data = "From external\nFrom: <none@example.org>\nTo: <none@example.org>\nDate: #{sent_at.rfc2822}\nSubject: Response\n\n" + body
            
            request.incoming_messages << incoming_message
            request.save!
            request.log_event("response",
                :api => true,
                :email => nil,
                :incoming_message_id => incoming_message.id,
                :smtp_message_id => nil
            )
        end
        
        head :no_content
    end
    
    protected
    def check_api_key
        @public_body = PublicBody.find_by_api_key(params[:k].gsub(' ', '+'))
        raise PermissionDenied if @public_body.nil?
    end
    
    private
    def make_url(*args)
        "http://" + MySociety::Config.get("DOMAIN", '127.0.0.1:3000') + "/" + args.join("/")
    end
end