aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/track_controller.rb2
-rw-r--r--app/helpers/application_helper.rb9
-rw-r--r--app/models/about_me_validator.rb8
-rw-r--r--app/models/change_email_validator.rb5
-rw-r--r--app/models/comment.rb39
-rw-r--r--app/models/outgoing_message.rb54
-rw-r--r--app/models/profile_photo.rb6
-rw-r--r--app/models/public_body.rb19
-rw-r--r--app/models/user.rb20
-rw-r--r--app/views/request/_followup.rhtml27
-rw-r--r--app/views/request/_sidebar.rhtml2
-rw-r--r--app/views/track/atom_feed.atom.builder25
-rw-r--r--app/views/track/atom_feed.atom.erb30
13 files changed, 136 insertions, 110 deletions
diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb
index 51e081c88..15da7f327 100644
--- a/app/controllers/track_controller.rb
+++ b/app/controllers/track_controller.rb
@@ -157,7 +157,7 @@ class TrackController < ApplicationController
def atom_feed_internal
@xapian_object = perform_search([InfoRequestEvent], @track_thing.track_query, @track_thing.params[:feed_sortby], nil, 25, 1)
respond_to do |format|
- format.atom { render :template => 'track/atom_feed' }
+ format.atom { render :template => 'track/atom_feed', :content_type => "application/atom+xml" }
format.json { render :json => @xapian_object.results.map { |r| r[:model].json_for_api(true,
lambda { |t| @template.highlight_and_excerpt(t, @xapian_object.words_to_highlight, 150) }
) } }
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index b9ba712a4..42f9d30f1 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -54,15 +54,12 @@ module ApplicationHelper
# Highlight words, also escapes HTML (other than spans that we add)
def highlight_words(t, words, html = true)
if html
- t = h(t)
- end
- if html
- t = highlight(t, words, '<span class="highlight">\1</span>')
+ highlight(h(t), words, '<span class="highlight">\1</span>').html_safe
else
- t = highlight(t, words, '*\1*')
+ highlight(t, words, '*\1*')
end
- return t
end
+
def highlight_and_excerpt(t, words, excount, html = true)
newt = excerpt(t, words[0], excount)
if not newt
diff --git a/app/models/about_me_validator.rb b/app/models/about_me_validator.rb
index 5e04c2761..8ee505ac8 100644
--- a/app/models/about_me_validator.rb
+++ b/app/models/about_me_validator.rb
@@ -17,10 +17,14 @@ class AboutMeValidator < ActiveRecord::BaseWithoutTable
column :about_me, :text, "I...", false
- def validate
+ # TODO: Switch to built in validations
+ validate :length_of_about_me
+
+ private
+
+ def length_of_about_me
if !self.about_me.blank? && self.about_me.size > 500
errors.add(:about_me, _("Please keep it shorter than 500 characters"))
end
end
-
end
diff --git a/app/models/change_email_validator.rb b/app/models/change_email_validator.rb
index 9ef25217d..2ddebb177 100644
--- a/app/models/change_email_validator.rb
+++ b/app/models/change_email_validator.rb
@@ -28,12 +28,15 @@ class ChangeEmailValidator < ActiveRecord::BaseWithoutTable
validates_presence_of :old_email, :message => N_("Please enter your old email address")
validates_presence_of :new_email, :message => N_("Please enter your new email address")
validates_presence_of :password, :message => N_("Please enter your password"), :unless => :changing_email
+ validate :password_and_format_of_email
def changing_email()
self.user_circumstance == 'change_email'
end
- def validate
+ private
+
+ def password_and_format_of_email
if !self.old_email.blank? && !MySociety::Validate.is_valid_email(self.old_email)
errors.add(:old_email, _("Old email doesn't look like a valid address"))
end
diff --git a/app/models/comment.rb b/app/models/comment.rb
index bcd1efca8..70f3ba00d 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -24,13 +24,13 @@ class Comment < ActiveRecord::Base
strip_attributes!
belongs_to :user
- #validates_presence_of :user # breaks during construction of new ones :(
-
- validates_inclusion_of :comment_type, :in => [ 'request' ]
belongs_to :info_request
-
has_many :info_request_events # in practice only ever has one
+ #validates_presence_of :user # breaks during construction of new ones :(
+ validates_inclusion_of :comment_type, :in => [ 'request' ]
+ validate :body_of_comment
+
def body
ret = read_attribute(:body)
if ret.nil?
@@ -40,6 +40,7 @@ class Comment < ActiveRecord::Base
ret = ret.gsub(/(?:\n\s*){2,}/, "\n\n") # remove excess linebreaks that unnecessarily space it out
ret
end
+
def raw_body
read_attribute(:body)
end
@@ -52,16 +53,6 @@ class Comment < ActiveRecord::Base
end
end
- # Check have edited comment
- def validate
- if self.body.empty? || self.body =~ /^\s+$/
- errors.add(:body, _("Please enter your annotation"))
- end
- if !MySociety::Validate.uses_mixed_capitals(self.body)
- errors.add(:body, _('Please write your annotation using a mixture of capital and lower case letters. This makes it easier for others to read.'))
- end
- end
-
# Return body for display as HTML
def get_body_for_html_display
text = self.body.strip
@@ -82,9 +73,21 @@ class Comment < ActiveRecord::Base
return Comment.find(:first, :conditions => [ "info_request_id = ? and body = ?", info_request_id, body ])
end
end
- def for_admin_column
- self.class.content_columns.each do |column|
- yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+
+ def for_admin_column
+ self.class.content_columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
+
+ private
+
+ def body_of_comment
+ if self.body.empty? || self.body =~ /^\s+$/
+ errors.add(:body, _("Please enter your annotation"))
+ end
+ if !MySociety::Validate.uses_mixed_capitals(self.body)
+ errors.add(:body, _('Please write your annotation using a mixture of capital and lower case letters. This makes it easier for others to read.'))
+ end
end
- end
end
diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb
index 441813e5f..c75894e6a 100644
--- a/app/models/outgoing_message.rb
+++ b/app/models/outgoing_message.rb
@@ -30,6 +30,7 @@ class OutgoingMessage < ActiveRecord::Base
validates_inclusion_of :status, :in => ['ready', 'sent', 'failed']
validates_inclusion_of :message_type, :in => ['initial_request', 'followup' ] #, 'complaint']
+ validate :format_of_body
belongs_to :incoming_message_followup, :foreign_key => 'incoming_message_followup_id', :class_name => 'IncomingMessage'
@@ -136,32 +137,6 @@ class OutgoingMessage < ActiveRecord::Base
end
end
- # Check have edited letter
- def validate
- if self.body.empty? || self.body =~ /\A#{get_salutation}\s+#{get_signoff}/ || self.body =~ /#{get_internal_review_insert_here_note}/
- if self.message_type == 'followup'
- if self.what_doing == 'internal_review'
- errors.add(:body, _("Please give details explaining why you want a review"))
- else
- errors.add(:body, _("Please enter your follow up message"))
- end
- elsif
- errors.add(:body, _("Please enter your letter requesting information"))
- else
- raise "Message id #{self.id} has type '#{self.message_type}' which validate can't handle"
- end
- end
- if self.body =~ /#{get_signoff}\s*\Z/m
- errors.add(:body, _("Please sign at the bottom with your name, or alter the \"%{signoff}\" signature" % { :signoff => get_signoff }))
- end
- if !MySociety::Validate.uses_mixed_capitals(self.body)
- errors.add(:body, _('Please write your message using a mixture of capital and lower case letters. This makes it easier for others to read.'))
- end
- if self.what_doing.nil? || !['new_information', 'internal_review', 'normal_sort'].include?(self.what_doing)
- errors.add(:what_doing_dummy, _('Please choose what sort of reply you are making.'))
- end
- end
-
# Deliver outgoing message
# Note: You can test this from script/console with, say:
# InfoRequest.find(1).outgoing_messages[0].send_message
@@ -275,6 +250,33 @@ class OutgoingMessage < ActiveRecord::Base
yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
end
end
+
+ private
+
+ def format_of_body
+ if self.body.empty? || self.body =~ /\A#{get_salutation}\s+#{get_signoff}/ || self.body =~ /#{get_internal_review_insert_here_note}/
+ if self.message_type == 'followup'
+ if self.what_doing == 'internal_review'
+ errors.add(:body, _("Please give details explaining why you want a review"))
+ else
+ errors.add(:body, _("Please enter your follow up message"))
+ end
+ elsif
+ errors.add(:body, _("Please enter your letter requesting information"))
+ else
+ raise "Message id #{self.id} has type '#{self.message_type}' which validate can't handle"
+ end
+ end
+ if self.body =~ /#{get_signoff}\s*\Z/m
+ errors.add(:body, _("Please sign at the bottom with your name, or alter the \"%{signoff}\" signature" % { :signoff => get_signoff }))
+ end
+ if !MySociety::Validate.uses_mixed_capitals(self.body)
+ errors.add(:body, _('Please write your message using a mixture of capital and lower case letters. This makes it easier for others to read.'))
+ end
+ if self.what_doing.nil? || !['new_information', 'internal_review', 'normal_sort'].include?(self.what_doing)
+ errors.add(:what_doing_dummy, _('Please choose what sort of reply you are making.'))
+ end
+ end
end
diff --git a/app/models/profile_photo.rb b/app/models/profile_photo.rb
index 6e605651d..73d7ca12b 100644
--- a/app/models/profile_photo.rb
+++ b/app/models/profile_photo.rb
@@ -23,6 +23,8 @@ class ProfilePhoto < ActiveRecord::Base
belongs_to :user
+ validate :data_and_draft_checks
+
# deliberately don't strip_attributes, so keeps raw photo properly
attr_accessor :x, :y, :w, :h
@@ -81,7 +83,9 @@ class ProfilePhoto < ActiveRecord::Base
end
end
- def validate
+ private
+
+ def data_and_draft_checks
if self.data.nil?
errors.add(:data, N_("Please choose a file containing your photo."))
return
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index f71520ee6..168b9f4c7 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -35,6 +35,8 @@ class PublicBody < ActiveRecord::Base
validates_uniqueness_of :short_name, :message => N_("Short name is already taken"), :if => Proc.new { |pb| pb.short_name != "" }
validates_uniqueness_of :name, :message => N_("Name is already taken")
+ validate :request_email_if_requestable
+
has_many :info_requests, :order => 'created_at desc'
has_many :track_things, :order => 'created_at desc'
has_many :censor_rules, :order => 'created_at desc'
@@ -135,15 +137,6 @@ class PublicBody < ActiveRecord::Base
self.first_letter = self.name.scan(/./mu)[0].upcase
end
- def validate
- # Request_email can be blank, meaning we don't have details
- if self.is_requestable?
- unless MySociety::Validate.is_valid_email(self.request_email)
- errors.add(:request_email, "Request email doesn't look like a valid email address")
- end
- end
- end
-
# If tagged "not_apply", then FOI/EIR no longer applies to authority at all
def not_apply?
return self.has_tag?('not_apply')
@@ -642,4 +635,12 @@ class PublicBody < ActiveRecord::Base
end
end
+ def request_email_if_requestable
+ # Request_email can be blank, meaning we don't have details
+ if self.is_requestable?
+ unless MySociety::Validate.is_valid_email(self.request_email)
+ errors.add(:request_email, "Request email doesn't look like a valid email address")
+ end
+ end
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 6e1e21481..617b51c60 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -50,6 +50,8 @@ class User < ActiveRecord::Base
'super',
], :message => N_('Admin level is not included in list')
+ validate :email_and_name_are_valid
+
acts_as_xapian :texts => [ :name, :about_me ],
:values => [
[ :created_at_numeric, 1, "created_at", :number ] # for sorting
@@ -108,15 +110,6 @@ class User < ActiveRecord::Base
self.comments.find(:all, :conditions => 'visible')
end
- def validate
- if self.email != "" && !MySociety::Validate.is_valid_email(self.email)
- errors.add(:email, _("Please enter a valid email address"))
- end
- if MySociety::Validate.is_valid_email(self.name)
- errors.add(:name, _("Please enter your name, not your email address, in the name field."))
- end
- end
-
# Don't display any leading/trailing spaces
# XXX we have strip_attributes! now, so perhaps this can be removed (might
# be still needed for existing cases)
@@ -413,6 +406,15 @@ class User < ActiveRecord::Base
self.salt = self.object_id.to_s + rand.to_s
end
+ def email_and_name_are_valid
+ if self.email != "" && !MySociety::Validate.is_valid_email(self.email)
+ errors.add(:email, _("Please enter a valid email address"))
+ end
+ if MySociety::Validate.is_valid_email(self.name)
+ errors.add(:name, _("Please enter your name, not your email address, in the name field."))
+ end
+ end
+
## Class methods
def User.encrypted_password(password, salt)
string_to_hash = password + salt # XXX need to add a secret here too?
diff --git a/app/views/request/_followup.rhtml b/app/views/request/_followup.rhtml
index 451932b8d..c329cea97 100644
--- a/app/views/request/_followup.rhtml
+++ b/app/views/request/_followup.rhtml
@@ -1,5 +1,10 @@
<div id="followup">
<% if (incoming_message.nil? || !incoming_message.valid_to_reply_to?)
+ # TRANSLATORS: This phrase completes the following sentences:
+ # Request an internal review from...
+ # Send a public follow up message to...
+ # Send a public reply to...
+ # Don't want to address your message to... ?
name_for_followup = _("the main FOI contact at {{public_body}}", :public_body => h(OutgoingMailer.name_for_followup(@info_request, nil)))
else
name_for_followup = h(OutgoingMailer.name_for_followup(@info_request, incoming_message))
@@ -8,16 +13,16 @@
<h1><%= _('Request an internal review from {{person_or_body}}', :person_or_body => name_for_followup) %>
</h1>
<% elsif incoming_message.nil? || !incoming_message.valid_to_reply_to? %>
- <h2><%= _('Send a public follow up message to {{person_or_body}}', :person_or_body => name_for_followup) %>
+ <h2><%= _('Send a public follow up message to {{person_or_body}}', :person_or_body => name_for_followup) %>
</h2>
<% else %>
- <h2><%= _('Send a public reply to {{person_or_body}}', :person_or_body => name_for_followup) %>
+ <h2><%= _('Send a public reply to {{person_or_body}}', :person_or_body => name_for_followup) %>
</h2>
<% end %>
<% if @info_request.who_can_followup_to(incoming_message).count > 0 %>
<div id="other_recipients">
- <%= _("Don't want to address your message to {{person_or_body}}? You can also write to:", :person_or_body => name_for_followup) %>
- <ul>
+ <%= _("Don't want to address your message to {{person_or_body}}? You can also write to:", :person_or_body => name_for_followup) %>
+ <ul>
<% @info_request.who_can_followup_to(incoming_message).each do |name, email, id| %>
<% if id.nil? && !incoming_message.nil? && incoming_message.valid_to_reply_to? %>
<li><%= link_to(_("the main FOI contact address for {{public_body}}", :public_body => name), show_response_no_followup_url(:id => @info_request.id, :incoming_message_id => nil)) %></li>
@@ -51,24 +56,24 @@
<% end %>
<p>
- <%= _('Please <strong>only</strong> write messages directly relating to your request {{request_link}}. If you would like to ask for information that was not in your original request, then <a href="{{new_request_link}}">file a new request</a>.', :request_link=>request_link(@info_request), :new_request_link => new_request_to_body_url(:url_name => @info_request.public_body.url_name)) %>
+ <%= _('Please <strong>only</strong> write messages directly relating to your request {{request_link}}. If you would like to ask for information that was not in your original request, then <a href="{{new_request_link}}">file a new request</a>.', :request_link=>request_link(@info_request), :new_request_link => new_request_to_body_url(:url_name => @info_request.public_body.url_name)) %>
</p>
<% status = @info_request.calculate_status %>
<% if status == 'waiting_response_overdue' %>
- <p><%= _('The response to your request has been <strong>delayed</strong>. You can say that,
+ <p><%= _('The response to your request has been <strong>delayed</strong>. You can say that,
by law, the authority should normally have responded
<strong>promptly</strong> and') %>
<% if @info_request.public_body.is_school? %>
- <%= _('in term time') %>
+ <%= _('in term time') %>
<% end %>
<%= _('by <strong>{{date}}</strong>',:date=>simple_date(@info_request.date_response_required_by)) %>
(<%= raw(_('<a href="%s">details</a>') % ["#{help_requesting_path}#quickly_response"]) %>).
-
+
</p>
<% elsif status == 'waiting_response_very_overdue' %>
<p>
- <%= _('The response to your request is <strong>long overdue</strong>. You can say that, by
+ <%= _('The response to your request is <strong>long overdue</strong>. You can say that, by
law, under all circumstances, the authority should have responded
by now') %> (<%= raw(_('<a href="%s">details</a>') % ["#{help_requesting_path}#quickly_response"]) %>).
</p>
@@ -97,8 +102,8 @@
-->
<div>
<%= radio_button "outgoing_message", "what_doing", "internal_review", :id => "internal_review" %>
- <label for="internal_review"><%= _('I am requesting an <strong>internal review</strong>') %>
- <%= raw(_('<a href="%s">what\'s that?</a>') % ["/help/unhappy"]) %>
+ <label for="internal_review"><%= _('I am requesting an <strong>internal review</strong>') %>
+ <%= raw(_('<a href="%s">what\'s that?</a>') % ["/help/unhappy"]) %>
</label>
</div>
<div>
diff --git a/app/views/request/_sidebar.rhtml b/app/views/request/_sidebar.rhtml
index d349bee14..5e0c6fd2d 100644
--- a/app/views/request/_sidebar.rhtml
+++ b/app/views/request/_sidebar.rhtml
@@ -25,7 +25,7 @@
<% else %>
<p><%= _('Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href="/help/about">read more</a>).') %></p>
<p><%= _('If you believe this request is not suitable, you can report it for attention by the site administrators') %></p>
- <%= link_to _("Report this request"), report_path, :class => "link_button_green", :method => "POST" %>
+ <%= button_to _("Report this request"), report_path, :class => "link_button_green" %>
<% end %>
<% end %>
<h2><%= _("Act on what you've learnt") %></h2>
diff --git a/app/views/track/atom_feed.atom.builder b/app/views/track/atom_feed.atom.builder
deleted file mode 100644
index d1e9310b8..000000000
--- a/app/views/track/atom_feed.atom.builder
+++ /dev/null
@@ -1,25 +0,0 @@
-atom_feed do |feed|
- feed.title(@track_thing.params[:title_in_rss])
- @highlight_words = @xapian_object.words_to_highlight
-
- for result in @xapian_object.results
- feed.entry(result[:model]) do |entry|
- # Get the HTML content from the same partial template as website search does
- content = ''
- if result[:model].class.to_s == 'InfoRequestEvent'
- content += render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request }
- else
- content = "<p><strong>Unknown search result type " + result[:model].class.to_s + "</strong></p>"
- end
- # Pull out the heading as separate item, from the partial template
- content.match(/(<span class="head">\s+<a href="[^>]*">(.*)<\/a>\s+<\/span>)/)
- heading = $1
- heading_text = $2
- content.sub!(heading, "")
- # Render the atom
- entry.title(heading_text, :type => 'html')
- entry.content(content, :type => 'html')
- end
- end
-end
-
diff --git a/app/views/track/atom_feed.atom.erb b/app/views/track/atom_feed.atom.erb
new file mode 100644
index 000000000..23c932308
--- /dev/null
+++ b/app/views/track/atom_feed.atom.erb
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:<%= request.host %>,2005:<%= request.fullpath.split(".")[0] %></id>
+ <link type="text/html" rel="alternate" href="<%= request.protocol + request.host_with_port %>"/>
+ <link type="application/atom+xml" rel="self" href="<%= request.url %>"/>
+ <title><%= @track_thing.params[:title_in_rss] %></title>
+ <% @xapian_object.results.each do |result| %>
+ <%
+ # Get the HTML content from the same partial template as website search does
+ content = ''
+ if result[:model].class.to_s == 'InfoRequestEvent'
+ content += render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request }
+ else
+ content = "<p><strong>Unknown search result type " + result[:model].class.to_s + "</strong></p>"
+ end
+ # Pull out the heading as separate item, from the partial template
+ content.match(/(<span class="head">\s+<a href="[^>]*">(.*)<\/a>\s+<\/span>)/)
+ heading = $1
+ heading_text = $2
+ content.sub!(heading, "")
+ %>
+ <entry>
+ <id>tag:<%= request.host %>,2005:<%= result[:model].class %>/<%= result[:model].id %></id>
+ <published><%= result[:model].created_at.xmlschema %></published>
+ <link type="text/html" rel="alternate" href="<%= polymorphic_url(result[:model]) %>"/>
+ <title type="html"><%= heading_text %></title>
+ <content type="html"><%= content %></content>
+ </entry>
+ <% end %>
+</feed>