aboutsummaryrefslogtreecommitdiffstats
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/incoming_message.rb2
-rw-r--r--app/models/info_request.rb46
-rw-r--r--app/models/info_request_event.rb2
-rw-r--r--app/models/public_body.rb11
-rw-r--r--app/models/raw_email.rb15
-rw-r--r--app/models/request_mailer.rb22
6 files changed, 80 insertions, 18 deletions
diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb
index 3419956d6..593590fb8 100644
--- a/app/models/incoming_message.rb
+++ b/app/models/incoming_message.rb
@@ -344,7 +344,7 @@ class IncomingMessage < ActiveRecord::Base
# Lotus notes quoting yeuch!
def remove_lotus_quoting(text, replacement = "FOLDED_QUOTED_SECTION")
text = text.dup
- name = Regexp.escape(self.info_request.user.name)
+ name = Regexp.escape(self.info_request.user_name)
# To end of message sections
# http://www.whatdotheyknow.com/request/university_investment_in_the_arm
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index 45819bfe7..d09acbcf6 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -33,7 +33,7 @@ class InfoRequest < ActiveRecord::Base
validates_format_of :title, :with => /[a-zA-Z]/, :message => N_("Please write a summary with some text in it"), :if => Proc.new { |info_request| !info_request.title.nil? && !info_request.title.empty? }
belongs_to :user
- #validates_presence_of :user_id # breaks during construction of new ones :(
+ validate :must_be_internal_or_external
belongs_to :public_body
validates_presence_of :public_body_id
@@ -104,6 +104,43 @@ class InfoRequest < ActiveRecord::Base
errors.add(:described_state, "is not a valid state") if
!InfoRequest.enumerate_states.include? described_state
end
+
+ # The request must either be internal, in which case it has
+ # a foreign key reference to a User object and no external_url or external_user_name,
+ # or else be external in which case it has no user_id but does have an external_url,
+ # and may optionally also have an external_user_name.
+ #
+ # External requests are requests that have been added using the API, whereas internal
+ # requests are requests made using the site.
+ def must_be_internal_or_external
+ # We must permit user_id and external_user_name both to be nil, because the system
+ # allows a request to be created by a non-logged-in user.
+ if !user_id.nil?
+ errors.add(:external_user_name, "must be null for an internal request") if !external_user_name.nil?
+ errors.add(:external_url, "must be null for an internal request") if !external_url.nil?
+ end
+ end
+
+ def is_external?
+ !external_url.nil?
+ end
+
+ def user_name
+ is_external? ? external_user_name : user.name
+ end
+
+ def user_name_slug
+ if is_external?
+ if external_user_name.nil?
+ fake_slug = "anonymous"
+ else
+ fake_slug = external_user_name.parameterize
+ end
+ public_body.url_name + "_"+fake_slug
+ else
+ user.url_name
+ end
+ end
@@custom_states_loaded = false
begin
@@ -232,7 +269,7 @@ public
return self.magic_email("request-")
end
def incoming_name_and_email
- return TMail::Address.address_from_name_and_email(self.user.name, self.incoming_email).to_s
+ return TMail::Address.address_from_name_and_email(self.user_name, self.incoming_email).to_s
end
# Subject lines for emails about the request
@@ -453,7 +490,7 @@ public
self.save!
end
self.info_request_events.each { |event| event.xapian_mark_needs_index } # for the "waiting_classification" index
- RequestMailer.deliver_new_response(self, incoming_message)
+ RequestMailer.deliver_new_response(self, incoming_message) if !is_external?
end
@@ -515,9 +552,6 @@ public
return false
end
- def can_have_attention_requested?
- end
-
# change status, including for last event for later historical purposes
def set_described_state(new_state, set_by = nil)
ActiveRecord::Base.transaction do
diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb
index 9a4f6d9fe..a827d19a4 100644
--- a/app/models/info_request_event.rb
+++ b/app/models/info_request_event.rb
@@ -118,7 +118,7 @@ class InfoRequestEvent < ActiveRecord::Base
:eager_load => [ :outgoing_message, :comment, { :info_request => [ :user, :public_body, :censor_rules ] } ]
def requested_by
- self.info_request.user.url_name
+ self.info_request.user_name_slug
end
def requested_from
# acts_as_xapian will detect translated fields via Globalize and add all the
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index 267b5d60c..a372de435 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -17,6 +17,7 @@
# notes :text default(""), not null
# first_letter :string(255) not null
# publication_scheme :text default(""), not null
+# api_key :string(255) not null
#
# models/public_body.rb:
@@ -28,6 +29,7 @@
# $Id: public_body.rb,v 1.160 2009-10-02 22:56:35 francis Exp $
require 'csv'
+require 'securerandom'
require 'set'
class PublicBody < ActiveRecord::Base
@@ -87,10 +89,13 @@ class PublicBody < ActiveRecord::Base
end
end
- # Make sure publication_scheme gets the correct default value.
- # (This would work automatically, were publication_scheme not a translated attribute)
def after_initialize
+ # Make sure publication_scheme gets the correct default value.
+ # (This would work automatically, were publication_scheme not a translated attribute)
self.publication_scheme = "" if self.publication_scheme.nil?
+
+ # Set an API key if there isn’t one
+ self.api_key = SecureRandom.base64(32) if self.api_key.nil?
end
# like find_by_url_name but also search historic url_name if none found
@@ -178,7 +183,7 @@ class PublicBody < ActiveRecord::Base
end
acts_as_versioned
- self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter'
+ self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter' << 'api_key'
class Version
attr_accessor :created_at
diff --git a/app/models/raw_email.rb b/app/models/raw_email.rb
index 1466e5d9c..3bb794684 100644
--- a/app/models/raw_email.rb
+++ b/app/models/raw_email.rb
@@ -19,13 +19,12 @@ class RawEmail < ActiveRecord::Base
has_one :incoming_message
- # We keep the old data_text field (which is of type text) for backwards
- # compatibility. We use the new data_binary field because only it works
- # properly in recent versions of PostgreSQL (get seg faults escaping
- # some binary strings).
-
def directory
request_id = self.incoming_message.info_request.id.to_s
+ if request_id.empty?
+ raise "Failed to find the id number of the associated request: has it been saved?"
+ end
+
if ENV["RAILS_ENV"] == "test"
return File.join(Rails.root, 'files/raw_email_test')
else
@@ -36,7 +35,11 @@ class RawEmail < ActiveRecord::Base
end
def filepath
- File.join(self.directory, self.incoming_message.id.to_s)
+ incoming_message_id = self.incoming_message.id.to_s
+ if incoming_message_id.empty?
+ raise "Failed to find the id number of the associated incoming message: has it been saved?"
+ end
+ File.join(self.directory, incoming_message_id)
end
def data=(d)
diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb
index 1b0bb48b9..03d26f237 100644
--- a/app/models/request_mailer.rb
+++ b/app/models/request_mailer.rb
@@ -28,6 +28,21 @@ class RequestMailer < ApplicationMailer
:filename => attachment_name
end
end
+
+ # Used when a response is uploaded using the API
+ def external_response(info_request, body, sent_at, attachments)
+ @from = blackhole_email
+ @recipients = info_request.incoming_name_and_email
+ @body = { :body => body }
+
+ # ActionMailer only works properly when the time is in the local timezone:
+ # see https://rails.lighthouseapp.com/projects/8994/tickets/3113-actionmailer-only-works-correctly-with-sent_on-times-that-are-in-the-local-time-zone
+ @sent_on = sent_at.dup.localtime
+
+ attachments.each do |attachment_hash|
+ attachment attachment_hash
+ end
+ end
# Incoming message arrived for a request, but new responses have been stopped.
def stopped_responses(info_request, email, raw_email_data)
@@ -241,7 +256,12 @@ class RequestMailer < ApplicationMailer
# Send email alerts for overdue requests
def self.alert_overdue_requests()
- info_requests = InfoRequest.find(:all, :conditions => [ "described_state = 'waiting_response' and awaiting_description = ?", false ], :include => [ :user ] )
+ info_requests = InfoRequest.find(:all,
+ :conditions => [
+ "described_state = 'waiting_response' and awaiting_description = ? and user_id is not null", false
+ ],
+ :include => [ :user ]
+ )
for info_request in info_requests
alert_event_id = info_request.last_event_forming_initial_request.id
# Only overdue requests