Commit 72a1c96d0f7bb0345cc7f06e89942cf4b58de9f6

Authored by Rodrigo Souto
2 parents f12dd0f6 ae71aa62

Merge branch 'stable' into postgres-tests

app/models/profile.rb
... ... @@ -298,7 +298,7 @@ class Profile < ActiveRecord::Base
298 298 validate :valid_template
299 299  
300 300 def valid_template
301   - if template_id.present? and !template.is_template
  301 + if template_id.present? && template && !template.is_template
302 302 errors.add(:template, _('is not a template.'))
303 303 end
304 304 end
... ...
app/views/blocks/location.html.erb
1 1 <% if profile.lat %>
2 2 <%= block_title block.title %>
3 3 <div class='the-localization-map'>
4   - <img src="http://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
  4 + <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 5 </div>
6 6 </div>
7 7 <% else %>
... ...
app/views/maps/edit_location.rhtml
... ... @@ -29,5 +29,5 @@
29 29  
30 30 <% end %>
31 31  
32   -<%= content_tag('script', '', :src => "http://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %>
  32 +<%= content_tag('script', '', :src => "https://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %>
33 33 <%= content_tag('script', '', :src => url_for(:controller => :maps, :action => :google_map), :type => 'text/javascript') %>
... ...
db/schema.rb
... ... @@ -221,7 +221,6 @@ ActiveRecord::Schema.define(:version =&gt; 20130711213046) do
221 221 t.string "source_type"
222 222 t.string "user_agent"
223 223 t.string "referrer"
224   - t.integer "group_id"
225 224 end
226 225  
227 226 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
... ...
debian/changelog
  1 +noosfero (0.44.3) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 14 Aug 2013 19:38:33 -0300
  6 +
1 7 noosfero (0.44.2) unstable; urgency=low
2 8  
3 9 * Bugfixes release
... ...
lib/feed_updater.rb
... ... @@ -19,6 +19,18 @@ end
19 19 # stops the process.
20 20 class FeedUpdater
21 21  
  22 + class ExceptionNotification < ActionMailer::Base
  23 + def mail error
  24 + environment = Environment.default
  25 +
  26 + recipients NOOSFERO_CONF['exception_recipients']
  27 + from environment.contact_email
  28 + reply_to environment.contact_email
  29 + subject "[#{environment.name}] Feed-updater: #{error.message}"
  30 + body render(:text => error.backtrace.join("\n"))
  31 + end
  32 + end
  33 +
22 34 # indicates how much time one feed will be left without updates
23 35 # (ActiveSupport::Duration). Default: <tt>4.hours</tt>
24 36 cattr_accessor :update_interval
... ... @@ -79,6 +91,8 @@ class FeedUpdater
79 91 feed_handler.process(container)
80 92 end
81 93 end
  94 + rescue Exception => e
  95 + FeedUpdater::ExceptionNotification.deliver_mail e if NOOSFERO_CONF['exception_recipients'].present?
82 96 end
83 97 end
84 98  
... ...
lib/noosfero.rb
... ... @@ -3,7 +3,7 @@ require &#39;fast_gettext&#39;
3 3  
4 4 module Noosfero
5 5 PROJECT = 'noosfero'
6   - VERSION = '0.44.2'
  6 + VERSION = '0.44.3'
7 7  
8 8 def self.pattern_for_controllers_in_directory(dir)
9 9 disjunction = controllers_in_directory(dir).join('|')
... ...
plugins/solr/lib/solr_plugin/search_helper.rb
... ... @@ -34,10 +34,6 @@ module SolrPlugin::SearchHelper
34 34 ],
35 35 }
36 36  
37   -# def asset_class(asset)
38   -# asset.to_s.singularize.camelize.constantize
39   -# end
40   -
41 37 def class_asset(klass)
42 38 klass.name.underscore.pluralize.to_sym
43 39 end
... ... @@ -111,6 +107,8 @@ module SolrPlugin::SearchHelper
111 107  
112 108 def asset_class(asset)
113 109 asset.to_s.singularize.camelize.constantize
  110 + rescue
  111 + asset.to_s.singularize.camelize.gsub('Plugin', 'Plugin::').constantize
114 112 end
115 113  
116 114 def set_facets_variables
... ...
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/class_methods.rb
... ... @@ -208,7 +208,7 @@ module ActsAsSolr #:nodoc:
208 208 # using eager loading for indexed associations.
209 209 def rebuild_solr_index(batch_size=300, options = {}, &finder)
210 210 finder ||= lambda do |ar, sql_options|
211   - ar.all sql_options.merge!({:order => self.primary_key, :include => configuration[:solr_includes].keys})
  211 + ar.all sql_options.merge!({:order => self.primary_key})
212 212 end
213 213 start_time = Time.now
214 214 options[:offset] ||= 0
... ...
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/instance_methods.rb
1 1 module ActsAsSolr #:nodoc:
2   -
  2 +
3 3 module InstanceMethods
4 4  
5 5 # Solr id is <class.name>:<id> to be unique across all models
... ... @@ -10,7 +10,7 @@ module ActsAsSolr #:nodoc:
10 10 # saves to the Solr index
11 11 def solr_save
12 12 return true if indexing_disabled?
13   - if evaluate_condition(:if, self)
  13 + if evaluate_condition(:if, self)
14 14 debug "solr_save: #{self.class.name} : #{record_id(self)}"
15 15 solr_add to_solr_doc
16 16 solr_commit if configuration[:auto_commit]
... ... @@ -38,9 +38,9 @@ module ActsAsSolr #:nodoc:
38 38 debug "to_solr_doc: creating doc for class: #{self.class.name}, id: #{record_id(self)}"
39 39 doc = Solr::Document.new
40 40 doc.boost = validate_boost(configuration[:boost]) if configuration[:boost]
41   -
  41 +
42 42 doc << {:id => solr_id,
43   - solr_configuration[:type_field] => self.class.name,
  43 + solr_configuration[:type_field] => Solr::Util.query_parser_escape(self.class.name),
44 44 solr_configuration[:primary_key_field] => record_id(self).to_s}
45 45  
46 46 # iterate through the fields and add them to the document,
... ... @@ -50,7 +50,7 @@ module ActsAsSolr #:nodoc:
50 50 field_boost = options[:boost] || solr_configuration[:default_boost]
51 51 field_type = get_solr_field_type(options[:type])
52 52 solr_name = options[:as] || field_name
53   -
  53 +
54 54 value = self.send("#{field_name}_for_solr") rescue nil
55 55 next if value.nil?
56 56  
... ... @@ -63,18 +63,18 @@ module ActsAsSolr #:nodoc:
63 63 field.boost = processed_boost
64 64 doc << field
65 65 end
66   -
  66 +
67 67 add_dynamic_attributes(doc)
68 68 add_includes(doc)
69 69 add_tags(doc)
70 70 add_space(doc)
71   -
  71 +
72 72 debug doc.to_json
73 73 doc
74 74 end
75 75  
76 76 private
77   -
  77 +
78 78 def debug(text)
79 79 logger.debug text rescue nil
80 80 end
... ... @@ -85,14 +85,14 @@ module ActsAsSolr #:nodoc:
85 85 doc << Solr::Field.new(:name => "lng_f", :value => local.longitude)
86 86 end
87 87 end
88   -
  88 +
89 89 def add_tags(doc)
90 90 taggings.each do |tagging|
91 91 doc << Solr::Field.new(:name => "tag_facet", :value => tagging.tag.name)
92 92 doc << Solr::Field.new(:name => "tag_t", :value => tagging.tag.name)
93 93 end if configuration[:taggable]
94 94 end
95   -
  95 +
96 96 def add_dynamic_attributes(doc)
97 97 dynamic_attributes.each do |attribute|
98 98 value = ERB::Util.html_escape(attribute.value)
... ... @@ -130,7 +130,7 @@ module ActsAsSolr #:nodoc:
130 130 end
131 131 end
132 132 end
133   -
  133 +
134 134 def include_value(record, options)
135 135 if options[:using].is_a? Proc
136 136 options[:using].call(record)
... ... @@ -159,14 +159,14 @@ module ActsAsSolr #:nodoc:
159 159 self.send(boost)
160 160 end
161 161 end
162   -
  162 +
163 163 boost_value || solr_configuration[:default_boost]
164 164 end
165   -
  165 +
166 166 def condition_block?(condition)
167 167 condition.respond_to?("call") && (condition.arity == 1 || condition.arity == -1)
168 168 end
169   -
  169 +
170 170 def evaluate_condition(which_condition, field)
171 171 condition = configuration[which_condition]
172 172 case condition
... ...
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/parser_methods.rb
... ... @@ -127,7 +127,7 @@ module ActsAsSolr #:nodoc:
127 127 classes = [self] + (self.subclasses || []) + (options[:models] || [])
128 128 classes.map do |klass|
129 129 next if klass.name.empty?
130   - "#{solr_configuration[:type_field]}:\"#{klass.name}\""
  130 + "#{solr_configuration[:type_field]}:\"#{Solr::Util.query_parser_escape klass.name}\""
131 131 end.compact.join(' OR ')
132 132 end
133 133  
... ...
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/select.rb
... ... @@ -12,22 +12,22 @@
12 12  
13 13 # "Abstract" base class, only useful with subclasses that add parameters
14 14 class Solr::Request::Select < Solr::Request::Base
15   -
  15 +
16 16 attr_reader :query_type
17   -
  17 +
18 18 def initialize(qt=nil, params={})
19 19 @query_type = qt
20 20 @select_params = params
21 21 end
22   -
  22 +
23 23 def response_format
24 24 :ruby
25 25 end
26   -
  26 +
27 27 def handler
28 28 'select'
29 29 end
30   -
  30 +
31 31 def content_type
32 32 'application/x-www-form-urlencoded; charset=utf-8'
33 33 end
... ... @@ -35,7 +35,7 @@ class Solr::Request::Select &lt; Solr::Request::Base
35 35 def to_hash
36 36 return {:qt => query_type, :wt => 'ruby', 'json.nl' => 'arrarr'}.merge(@select_params)
37 37 end
38   -
  38 +
39 39 def to_s
40 40 raw_params = self.to_hash
41 41  
... ... @@ -50,5 +50,5 @@ class Solr::Request::Select &lt; Solr::Request::Base
50 50  
51 51 http_params.join("&")
52 52 end
53   -
  53 +
54 54 end
... ...
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/tasks/solr.rake
1 1 namespace :solr do
2 2  
3   - APACHE_MIRROR = ENV['APACHE_MIRROR'] || "http://ftp.unicamp.br/pub/apache"
  3 + APACHE_MIRROR = ENV['APACHE_MIRROR'] || "https://archive.apache.org/dist"
4 4 SOLR_VERSION = '3.6.2'
5 5 SOLR_FILENAME = "apache-solr-#{SOLR_VERSION}.tgz"
6 6 SOLR_MD5SUM = 'e9c51f51265b070062a9d8ed50b84647'
... ... @@ -177,7 +177,7 @@ namespace :solr do
177 177 models.each do |model|
178 178 if clear_first
179 179 puts "Clearing index for #{model}..."
180   - ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "#{model.solr_configuration[:type_field]}:#{Solr::Util.query_parser_escape(model.name)}"))
  180 + ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "#{model.solr_configuration[:type_field]}:#{model.name.gsub ':', "\\:"}"))
181 181 ActsAsSolr::Post.execute(Solr::Request::Commit.new)
182 182 end
183 183  
... ...
public/500.html
... ... @@ -55,13 +55,13 @@
55 55  
56 56  
57 57 <div id='es' style='display: none' class='message'>
58   - <h1>Temporary system problem</h1>
  58 + <h1>Problema temporal del sistema</h1>
59 59 <p>
60   - Our technical team is working on it, please try again later. Sorry for the inconvenience.
  60 + Nuestro equipo técnico está trabajando en ello, por favor, inténtalo de nuevo más tarde. Disculpa las molestias.
61 61 </p>
62 62 <ul>
63   - <li><a href='javascript: history.back()'>Go back</a></li>
64   - <li><a href='/'>Go to the site home page</a></li>
  63 + <li><a href='javascript: history.back()'>Regresar</a></li>
  64 + <li><a href='/'>Ir a la página de inicio del sitio</a></li>
65 65 </ul>
66 66 </div>
67 67  
... ... @@ -90,6 +90,18 @@
90 90 </div>
91 91  
92 92  
  93 + <div id='it' style='display: none' class='message'>
  94 + <h1>Temporary system problem</h1>
  95 + <p>
  96 + Our technical team is working on it, please try again later. Sorry for the inconvenience.
  97 + </p>
  98 + <ul>
  99 + <li><a href='javascript: history.back()'>Go back</a></li>
  100 + <li><a href='/'>Go to the site home page</a></li>
  101 + </ul>
  102 + </div>
  103 +
  104 +
93 105 <div id='pt' style='display: none' class='message'>
94 106 <h1>Problema temporário no sistema</h1>
95 107 <p>
... ... @@ -127,6 +139,8 @@
127 139  
128 140 <a href="javascript: display_error_message('hy')">հայերեն լեզու</a>
129 141  
  142 + <a href="javascript: display_error_message('it')">Italiano</a>
  143 +
130 144 <a href="javascript: display_error_message('pt')">Português</a>
131 145  
132 146 <a href="javascript: display_error_message('ru')">русский язык</a>
... ...
public/503.html
... ... @@ -43,9 +43,9 @@
43 43  
44 44  
45 45 <div id='es' style='display: none' class='message'>
46   - <h1>System maintainance</h1>
  46 + <h1>Mantenimeinto del sistema</h1>
47 47 <p>
48   - This system is under maintainance. It should be back in a few moments.
  48 + Este sistema está en mantenimiento. Debería regresar en unos momentos.
49 49 </p>
50 50 </div>
51 51  
... ... @@ -66,6 +66,14 @@
66 66 </div>
67 67  
68 68  
  69 + <div id='it' style='display: none' class='message'>
  70 + <h1>System maintainance</h1>
  71 + <p>
  72 + This system is under maintainance. It should be back in a few moments.
  73 + </p>
  74 + </div>
  75 +
  76 +
69 77 <div id='pt' style='display: none' class='message'>
70 78 <h1>Manutenção do sistema</h1>
71 79 <p>
... ... @@ -95,6 +103,8 @@
95 103  
96 104 <a href="javascript: display_error_message('hy')">հայերեն լեզու</a>
97 105  
  106 + <a href="javascript: display_error_message('it')">Italiano</a>
  107 +
98 108 <a href="javascript: display_error_message('pt')">Português</a>
99 109  
100 110 <a href="javascript: display_error_message('ru')">русский язык</a>
... ...
test/unit/location_block_test.rb
... ... @@ -29,11 +29,11 @@ class LocationBlockTest &lt; ActiveSupport::TestCase
29 29 assert_equal '', LocationBlock.new.title
30 30 end
31 31  
32   - should 'use google maps api v3' do
  32 + should 'use google maps api v3 with ssl' do
33 33 @block.owner.lat = '-12.34'; @block.owner.save!
34 34 content = extract_block_content(@block.content)
35 35  
36   - assert_match 'http://maps.google.com/maps/api/staticmap', content
  36 + assert_match 'https://maps.google.com/maps/api/staticmap', content
37 37 assert_no_match /key=/, content
38 38 end
39 39  
... ...
test/unit/profile_test.rb
... ... @@ -1379,6 +1379,16 @@ class ProfileTest &lt; ActiveSupport::TestCase
1379 1379 assert_not_includes Profile.templates(Environment.default), profile
1380 1380 end
1381 1381  
  1382 + should 'not crash on a profile update with a destroyed template' do
  1383 + template = fast_create(Profile, :is_template => true)
  1384 + profile = fast_create(Profile, :template_id => template.id)
  1385 + template.destroy
  1386 +
  1387 + assert_nothing_raised do
  1388 + Profile.find(profile.id).save!
  1389 + end
  1390 + end
  1391 +
1382 1392 should 'provide URL to leave' do
1383 1393 profile = build(Profile, :identifier => 'testprofile')
1384 1394 assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => false}, profile.leave_url)
... ...
vendor/plugins/delayed_job/lib/delayed/worker.rb
... ... @@ -10,12 +10,12 @@ module Delayed
10 10 self.max_attempts = 25
11 11 self.max_run_time = 4.hours
12 12 self.default_priority = 0
13   -
  13 +
14 14 # By default failed jobs are destroyed after too many attempts. If you want to keep them around
15 15 # (perhaps to inspect the reason for the failure), set this to false.
16 16 cattr_accessor :destroy_failed_jobs
17 17 self.destroy_failed_jobs = true
18   -
  18 +
19 19 self.logger = if defined?(Merb::Logger)
20 20 Merb.logger
21 21 elsif defined?(RAILS_DEFAULT_LOGGER)
... ... @@ -24,9 +24,9 @@ module Delayed
24 24  
25 25 # name_prefix is ignored if name is set directly
26 26 attr_accessor :name_prefix
27   -
  27 +
28 28 cattr_reader :backend
29   -
  29 +
30 30 def self.backend=(backend)
31 31 if backend.is_a? Symbol
32 32 require "delayed/backend/#{backend}"
... ... @@ -35,7 +35,7 @@ module Delayed
35 35 @@backend = backend
36 36 silence_warnings { ::Delayed.const_set(:Job, backend) }
37 37 end
38   -
  38 +
39 39 def self.guess_backend
40 40 self.backend ||= if defined?(ActiveRecord)
41 41 :active_record
... ... @@ -97,7 +97,7 @@ module Delayed
97 97 ensure
98 98 Delayed::Job.clear_locks!(name)
99 99 end
100   -
  100 +
101 101 # Do num jobs and return stats on success/failure.
102 102 # Exit early if interrupted.
103 103 def work_off(num = 100)
... ... @@ -117,7 +117,7 @@ module Delayed
117 117  
118 118 return [success, failure]
119 119 end
120   -
  120 +
121 121 def run(job)
122 122 runtime = Benchmark.realtime do
123 123 Timeout.timeout(self.class.max_run_time.to_i) { job.invoke_job }
... ... @@ -129,7 +129,7 @@ module Delayed
129 129 handle_failed_job(job, e)
130 130 return false # work failed
131 131 end
132   -
  132 +
133 133 # Reschedule the job in the future (when a job fails).
134 134 # Uses an exponential scale depending on the number of failed attempts.
135 135 def reschedule(job, time = nil)
... ... @@ -162,13 +162,13 @@ module Delayed
162 162 end
163 163  
164 164 protected
165   -
  165 +
166 166 def handle_failed_job(job, error)
167 167 job.last_error = error.message + "\n" + error.backtrace.join("\n")
168 168 say "#{job.name} failed with #{error.class.name}: #{error.message} - #{job.attempts} failed attempts", Logger::ERROR
169 169 reschedule(job)
170 170 end
171   -
  171 +
172 172 # Run the next job we can get an exclusive lock on.
173 173 # If no jobs are left we return nil
174 174 def reserve_and_run_one_job
... ...
vendor/plugins/monkey_patches/rescue_delayed_job_crashes/init.rb 0 → 100644
... ... @@ -0,0 +1,48 @@
  1 +Delayed::Worker.module_eval do
  2 + # based on https://groups.google.com/forum/#!topic/delayed_job/ZGMUFFppNgs
  3 + class Delayed::Worker::ExceptionNotification < ActionMailer::Base
  4 + def mail error
  5 + environment = Environment.default
  6 +
  7 + recipients NOOSFERO_CONF['exception_recipients']
  8 + from environment.contact_email
  9 + reply_to environment.contact_email
  10 + subject "[#{environment.name}] DelayedJob: #{error.message}"
  11 + body render(:text => error.backtrace.join("\n"))
  12 + end
  13 + end
  14 +
  15 + def handle_failed_job_with_notification(job, error)
  16 + Delayed::Worker::ExceptionNotification.deliver_mail error if NOOSFERO_CONF['exception_recipients'].present?
  17 + handle_failed_job_without_notification job, error
  18 + end
  19 + alias_method_chain :handle_failed_job, :notification
  20 +
  21 + def handle_failed_job_with_rescue(job, error)
  22 + handle_failed_job_without_rescue(job, error)
  23 + rescue => e # don't crash here
  24 + end
  25 + alias_method_chain :handle_failed_job, :rescue
  26 +
  27 + protected
  28 +
  29 + # This code must be replicated because there is no other way to pass the job
  30 + # through and use alias_method_chain as we used on the previous method
  31 + def reserve_and_run_one_job
  32 + # We get up to 5 jobs from the db. In case we cannot get exclusive access to a job we try the next.
  33 + # this leads to a more even distribution of jobs across the worker processes
  34 + job = Delayed::Job.find_available(name, 5, self.class.max_run_time).detect do |job|
  35 + if job.lock_exclusively!(self.class.max_run_time, name)
  36 + say "acquired lock on #{job.name}"
  37 + true
  38 + else
  39 + say "failed to acquire exclusive lock for #{job.name}", Logger::WARN
  40 + false
  41 + end
  42 + end
  43 +
  44 + run(job) if job
  45 + rescue => e
  46 + handle_failed_job(job, e)
  47 + end
  48 +end
... ...