Commit c9eccb09a357ff5a3da2dca56c26c2fc8a52a4d5

Authored by Rodrigo Souto
2 parents e9bc0f67 9a383b33

Merge branch 'stable'

Conflicts:
	db/schema.rb
	test/unit/person_test.rb
AUTHORS
... ... @@ -149,6 +149,7 @@ João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>
149 149 João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
150 150 Joenio Costa <joenio@colivre.coop.br>
151 151 Josef Spillner <josef.spillner@tu-dresden.de>
  152 +Junior Silva <juniorsilva1001@gmail.com>
152 153 Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>
153 154 Keilla Menezes <keilla@colivre.coop.br>
154 155 Larissa Reis <larissa@colivre.coop.br>
... ... @@ -161,6 +162,7 @@ Lucas Melo &lt;lucaspradomelo@gmail.com&gt;
161 162 Luis David Aguilar Carlos <ludwig9003@gmail.com>
162 163 Martín Olivera <molivera@solar.org.ar>
163 164 Moises Machado <moises@colivre.coop.br>
  165 +Naíla Alves <naila@colivre.coop.br>
164 166 Nanda Lopes <nanda.listas+psl@gmail.com>
165 167 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
166 168 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
... ... @@ -197,6 +199,7 @@ root &lt;root@debian.sdr.serpro&gt;
197 199 Samuel R. C. Vale <srcvale@holoscopio.com>
198 200 Valessio Brito <valessio@gmail.com>
199 201 vfcosta <vfcosta@gmail.com>
  202 +Victor Costa <vfcosta@gmail.com>
200 203 Vinicius Cubas Brand <viniciuscb@gmail.com>
201 204 Visita <visita@debian.(none)>
202 205 Yann Lugrin <yann.lugrin@liquid-concept.ch>
... ...
app/controllers/application_controller.rb
... ... @@ -2,7 +2,7 @@ class ApplicationController &lt; ActionController::Base
2 2  
3 3 before_filter :setup_multitenancy
4 4 before_filter :detect_stuff_by_domain
5   - before_filter :init_noosfero_plugins
  5 + before_filter :init_noosfero_plugins_controller_filters
6 6 before_filter :allow_cross_domain_access
7 7  
8 8 def allow_cross_domain_access
... ... @@ -21,8 +21,12 @@ class ApplicationController &lt; ActionController::Base
21 21 include ApplicationHelper
22 22 layout :get_layout
23 23 def get_layout
24   - prepend_view_path('public/' + theme_path)
25   - theme_option(:layout) || 'application'
  24 + theme_layout = theme_option(:layout)
  25 + if theme_layout
  26 + theme_view_file('layouts/'+theme_layout) || theme_layout
  27 + else
  28 + 'application'
  29 + end
26 30 end
27 31  
28 32 filter_parameter_logging :password
... ... @@ -122,22 +126,21 @@ class ApplicationController &lt; ActionController::Base
122 126  
123 127 include Noosfero::Plugin::HotSpot
124 128  
125   - def init_noosfero_plugins
126   - plugins.each do |plugin|
127   - prepend_view_path(plugin.class.view_path)
128   - end
129   - init_noosfero_plugins_controller_filters
130   - end
131   -
132 129 # This is a generic method that initialize any possible filter defined by a
133 130 # plugin to the current controller being initialized.
134 131 def init_noosfero_plugins_controller_filters
135 132 plugins.each do |plugin|
136 133 filters = plugin.send(self.class.name.underscore + '_filters')
137 134 filters = [filters] if !filters.kind_of?(Array)
  135 + controller_filters = self.class.filter_chain.map {|c| c.method }
138 136 filters.each do |plugin_filter|
139   - self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {}))
140   - self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block])
  137 + filter_method = plugin.class.name.underscore.gsub('/','_') + '_' + plugin_filter[:method_name]
  138 + unless controller_filters.include?(filter_method)
  139 + self.class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {}))
  140 + self.class.send(:define_method, filter_method) do
  141 + instance_eval(&plugin_filter[:block]) if environment.plugin_enabled?(plugin.class)
  142 + end
  143 + end
141 144 end
142 145 end
143 146 end
... ...
app/controllers/public/account_controller.rb
... ... @@ -274,7 +274,7 @@ class AccountController &lt; ApplicationController
274 274 def user_data
275 275 user_data =
276 276 if logged_in?
277   - current_user.data_hash
  277 + current_user.data_hash(gravatar_default)
278 278 else
279 279 { }
280 280 end
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -96,7 +96,7 @@ class ContentViewerController &lt; ApplicationController
96 96 end
97 97  
98 98 if @page.folder? && @page.gallery?
99   - @images = @page.images
  99 + @images = @page.images.select{ |a| a.display_to? user }
100 100 @images = @images.paginate(:per_page => per_page, :page => params[:npage]) unless params[:slideshow]
101 101 end
102 102  
... ...
app/helpers/application_helper.rb
... ... @@ -38,6 +38,8 @@ module ApplicationHelper
38 38  
39 39 include LayoutHelper
40 40  
  41 + include Noosfero::Gravatar
  42 +
41 43 def locale
42 44 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
43 45 end
... ... @@ -366,7 +368,7 @@ module ApplicationHelper
366 368 def current_theme
367 369 @current_theme ||=
368 370 begin
369   - if (session[:theme])
  371 + if session[:theme]
370 372 session[:theme]
371 373 else
372 374 # utility for developers: set the theme to 'random' in development mode and
... ... @@ -375,7 +377,7 @@ module ApplicationHelper
375 377 if ENV['RAILS_ENV'] == 'development' && environment.theme == 'random'
376 378 @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand
377 379 @random_theme
378   - elsif ENV['RAILS_ENV'] == 'development' && params[:theme] && File.exists?(File.join(Rails.root, 'public/designs/themes', params[:theme]))
  380 + elsif ENV['RAILS_ENV'] == 'development' && respond_to?(:params) && params[:theme] && File.exists?(File.join(Rails.root, 'public/designs/themes', params[:theme]))
379 381 params[:theme]
380 382 else
381 383 if profile && !profile.theme.nil?
... ... @@ -397,16 +399,23 @@ module ApplicationHelper
397 399 end
398 400 end
399 401  
400   - def theme_include(template)
  402 + def theme_view_file(template)
401 403 ['.rhtml', '.html.erb'].each do |ext|
402   - file = (RAILS_ROOT + '/public' + theme_path + '/' + template + ext)
403   - if File.exists?(file)
404   - return render :file => file, :use_full_path => false
405   - end
  404 + file = (RAILS_ROOT + '/public' + theme_path + '/' + template + ext)
  405 + return file if File.exists?(file)
406 406 end
407 407 nil
408 408 end
409 409  
  410 + def theme_include(template)
  411 + file = theme_view_file(template)
  412 + if file
  413 + render :file => file, :use_full_path => false
  414 + else
  415 + nil
  416 + end
  417 + end
  418 +
410 419 def theme_favicon
411 420 return '/designs/themes/' + current_theme + '/favicon.ico' if profile.nil? || profile.theme.nil?
412 421 if File.exists?(File.join(RAILS_ROOT, 'public', theme_path, 'favicon.ico'))
... ... @@ -589,33 +598,8 @@ module ApplicationHelper
589 598 :class => 'vcard'), :class => 'common-profile-list-block')
590 599 end
591 600  
592   - def gravatar_url_for(email, options = {})
593   - # Ta dando erro de roteamento
594   - default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil
595   - url_for( { :gravatar_id => Digest::MD5.hexdigest(email.to_s),
596   - :host => 'www.gravatar.com',
597   - :protocol => 'http://',
598   - :only_path => false,
599   - :controller => 'avatar.php',
600   - :d => default
601   - }.merge(options) )
602   - end
603   -
604   - def str_gravatar_url_for(email, options = {})
605   - default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil
606   - url = 'http://www.gravatar.com/avatar.php?gravatar_id=' +
607   - Digest::MD5.hexdigest(email.to_s)
608   - {
609   - :only_path => false,
610   - :d => default
611   - }.merge(options).each { |k,v|
612   - url += ( '&%s=%s' % [ k,v ] )
613   - }
614   - url
615   - end
616   -
617   - def gravatar_profile_url(email)
618   - 'http://www.gravatar.com/'+ Digest::MD5.hexdigest(email.to_s)
  601 + def gravatar_default
  602 + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar']
619 603 end
620 604  
621 605 attr_reader :environment
... ... @@ -940,7 +924,7 @@ module ApplicationHelper
940 924 (@category ? " - #{@category.full_name}" : '')
941 925 end
942 926  
943   - # DEPRECATED. Do not use this·
  927 + # DEPRECATED. Do not use this.
944 928 def import_controller_stylesheets(options = {})
945 929 stylesheet_import( "controller_"+ @controller.controller_name(), options )
946 930 end
... ... @@ -1158,12 +1142,12 @@ module ApplicationHelper
1158 1142 pending_tasks_count = link_to(count.to_s, @environment.top_url + '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks"))
1159 1143 end
1160 1144  
1161   - (_("<span class='welcome'>Welcome,</span> %s") % link_to('<i></i><strong>{login}</strong>', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) +
  1145 + (_("<span class='welcome'>Welcome,</span> %s") % link_to('<i style="background-image:url({avatar})"></i><strong>{login}</strong>', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) +
1162 1146 render_environment_features(:usermenu) +
1163   - link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') +
  1147 + link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') +
1164 1148 manage_enterprises.to_s +
1165 1149 manage_communities.to_s +
1166   - link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) +
  1150 + link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :class => 'ctrl-panel', :title => _("Configure your personal account and content")) +
1167 1151 pending_tasks_count +
1168 1152 link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
1169 1153 end
... ...
app/models/person.rb
... ... @@ -476,7 +476,7 @@ class Person &lt; Profile
476 476 end
477 477  
478 478 def activities
479   - Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' ORDER BY updated_at DESC")
  479 + Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' and action_tracker.verb != 'reply_scrap_on_self' ORDER BY updated_at DESC")
480 480 end
481 481  
482 482 # by default, all fields are private
... ... @@ -484,6 +484,13 @@ class Person &lt; Profile
484 484 self.fields_privacy.nil? ? [] : self.fields_privacy.reject{ |k, v| v != 'public' }.keys.map(&:to_s)
485 485 end
486 486  
  487 + include Noosfero::Gravatar
  488 +
  489 + def profile_custom_icon(gravatar_default=nil)
  490 + (self.image.present? && self.image.public_filename(:icon)) ||
  491 + gravatar_profile_image_url(self.email, :size=>20, :d => gravatar_default)
  492 + end
  493 +
487 494 protected
488 495  
489 496 def followed_by?(profile)
... ...
app/models/profile.rb
... ... @@ -845,8 +845,10 @@ private :generate_url, :url_options
845 845 }[amount] || _("%s members") % amount
846 846 end
847 847  
848   - def profile_custom_icon
849   - self.image.public_filename(:icon) unless self.image.blank?
  848 + include Noosfero::Gravatar
  849 +
  850 + def profile_custom_icon(gravatar_default=nil)
  851 + image.public_filename(:icon) if image.present?
850 852 end
851 853  
852 854 def jid(options = {})
... ...
app/models/scrap.rb
... ... @@ -14,9 +14,11 @@ class Scrap &lt; ActiveRecord::Base
14 14  
15 15 named_scope :not_replies, :conditions => {:scrap_id => nil}
16 16  
17   - track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.receiver != s.sender}, :custom_target => :action_tracker_target
  17 + track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target
18 18  
19   - track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.receiver == s.sender}
  19 + track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}
  20 +
  21 + track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver}
20 22  
21 23 after_create do |scrap|
22 24 scrap.root.update_attribute('updated_at', DateTime.now) unless scrap.root.nil?
... ... @@ -25,6 +27,12 @@ class Scrap &lt; ActiveRecord::Base
25 27  
26 28 before_validation :strip_all_html_tags
27 29  
  30 + def top_root
  31 + scrap = self
  32 + scrap = Scrap.find(scrap.scrap_id) while scrap.scrap_id
  33 + scrap
  34 + end
  35 +
28 36 def strip_all_html_tags
29 37 sanitizer = HTML::WhiteListSanitizer.new
30 38 self.content = sanitizer.sanitize(self.content, :tags => [])
... ...
app/models/user.rb
... ... @@ -290,19 +290,21 @@ class User &lt; ActiveRecord::Base
290 290 end
291 291 end
292 292  
293   - def data_hash
  293 + def data_hash(gravatar_default = nil)
294 294 friends_list = {}
295 295 enterprises = person.enterprises.map { |e| { 'name' => e.short_name, 'identifier' => e.identifier } }
296 296 self.person.friends.online.map do |person|
297 297 friends_list[person.identifier] = {
298   - 'avatar' => person.profile_custom_icon,
  298 + 'avatar' => person.profile_custom_icon(gravatar_default),
299 299 'name' => person.short_name,
300 300 'jid' => person.full_jid,
301 301 'status' => person.user.chat_status,
302 302 }
303 303 end
  304 +
304 305 {
305 306 'login' => self.login,
  307 + 'avatar' => self.person.profile_custom_icon(gravatar_default),
306 308 'is_admin' => self.person.is_admin?,
307 309 'since_month' => self.person.created_at.month,
308 310 'since_year' => self.person.created_at.year,
... ...
app/views/comment/_comment.rhtml
... ... @@ -13,11 +13,11 @@
13 13 <% else %>
14 14 <% url_image, status_class = comment.author_id ?
15 15 [comment.removed_user_image, 'icon-user-removed'] :
16   - [str_gravatar_url_for( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %>
  16 + [gravatar_profile_image_url( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %>
17 17  
18 18 <%= link_to(
19 19 image_tag(url_image, :onerror=>'gravatarCommentFailback(this)',
20   - 'data-gravatar'=>str_gravatar_url_for(comment.email, :size=>50)) +
  20 + 'data-gravatar'=>gravatar_profile_image_url(comment.email, :size=>50)) +
21 21 content_tag('span', comment.author_name, :class => 'comment-info') +
22 22 content_tag('span', comment.message,
23 23 :class => 'comment-user-status ' + status_class),
... ...
app/views/profile/_comment.rhtml
... ... @@ -16,11 +16,11 @@
16 16 <% else %>
17 17 <% url_image, status_class = comment.author_id ?
18 18 [comment.removed_user_image, 'icon-user-removed'] :
19   - [str_gravatar_url_for( comment.email ), 'icon-user-unknown'] %>
  19 + [gravatar_profile_image_url( comment.email ), 'icon-user-unknown'] %>
20 20  
21 21 <%= link_to(
22 22 image_tag(url_image, :onerror=>'gravatarCommentFailback(this)',
23   - 'data-gravatar'=>str_gravatar_url_for(comment.email)) +
  23 + 'data-gravatar'=>gravatar_profile_image_url(comment.email)) +
24 24 content_tag('span', comment.author_name, :class => 'comment-info') +
25 25 content_tag('span', comment.message,
26 26 :class => 'comment-user-status comment-user-status-wall ' + status_class),
... ...
app/views/profile/_reply_scrap_on_self.rhtml 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_leave_scrap.rhtml
0 2 \ No newline at end of file
... ...
app/views/search/_comment.rhtml
... ... @@ -8,7 +8,7 @@
8 8 <%# unauthenticated user: display gravatar icon %>
9 9 <%= content_tag 'span', '&nbsp;',
10 10 :class => 'comment-picture',
11   - :style => 'background-image:url(%s)' % str_gravatar_url_for( comment.email, :size => 20 )
  11 + :style => 'background-image:url(%s)' % gravatar_profile_image_url( comment.email, :size => 20 )
12 12 %>
13 13 <%- end %>
14 14 <strong><%= link_to(comment.title, comment.url) %></strong>
... ...
config/environment.rb
... ... @@ -48,7 +48,7 @@ Rails::Initializer.run do |config|
48 48  
49 49 # Use the database for sessions instead of the file system
50 50 # (create the session table with 'rake db:sessions:create')
51   - # config.action_controller.session_store = :active_record_store
  51 + config.action_controller.session_store = :active_record_store
52 52  
53 53 # Use SQL instead of Active Record's schema dumper when creating the test database.
54 54 # This is necessary if your schema can't be completely dumped by the schema dumper,
... ...
config/initializers/action_tracker.rb
... ... @@ -2,6 +2,8 @@ require &#39;noosfero/i18n&#39;
2 2  
3 3 # ActionTracker plugin stuff
4 4  
  5 +@reply_scrap_description = lambda { _('sent a message to %{receiver}: <br /> "%{message}"') % { :receiver => "{{link_to(ta.get_receiver_name, ta.get_receiver_url)}}", :message => "{{auto_link_urls(ta.get_content)}}" } }
  6 +
5 7 ActionTrackerConfig.verbs = {
6 8  
7 9 :create_article => {
... ... @@ -49,12 +51,16 @@ ActionTrackerConfig.verbs = {
49 51 },
50 52  
51 53 :leave_scrap => {
52   - :description => lambda { _('sent a message to %{receiver}: <br /> "%{message}"') % { :receiver => "{{link_to(ta.get_receiver_name, ta.get_receiver_url)}}", :message => "{{auto_link_urls(ta.get_content)}}" } }
  54 + :description => @reply_scrap_description
53 55 },
54 56  
55 57 :leave_scrap_to_self => {
56 58 :description => lambda { _('wrote: <br /> "%{text}"') % { :text => "{{auto_link_urls(ta.get_content)}}" } }
57   - }
  59 + },
  60 +
  61 + :reply_scrap_on_self => {
  62 + :description => @reply_scrap_description
  63 + },
58 64 }
59 65  
60 66 ActionTrackerConfig.current_user_method = :current_person
... ...
db/migrate/20130918183842_create_sessions.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +class CreateSessions < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :sessions do |t|
  4 + t.string :session_id, :null => false
  5 + t.text :data
  6 + t.timestamps
  7 + end
  8 +
  9 + add_index :sessions, :session_id
  10 + add_index :sessions, :updated_at
  11 + end
  12 +
  13 + def self.down
  14 + drop_table :sessions
  15 + end
  16 +end
... ...
db/schema.rb
... ... @@ -9,7 +9,7 @@
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11  
12   -ActiveRecord::Schema.define(:version => 20131116165327) do
  12 +ActiveRecord::Schema.define(:version => 20131121162641) do
13 13  
14 14 create_table "abuse_reports", :force => true do |t|
15 15 t.integer "reporter_id"
... ... @@ -524,6 +524,16 @@ ActiveRecord::Schema.define(:version =&gt; 20131116165327) do
524 524 t.integer "context_id"
525 525 end
526 526  
  527 + create_table "sessions", :force => true do |t|
  528 + t.string "session_id", :null => false
  529 + t.text "data"
  530 + t.datetime "created_at"
  531 + t.datetime "updated_at"
  532 + end
  533 +
  534 + add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
  535 + add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
  536 +
527 537 create_table "taggings", :force => true do |t|
528 538 t.integer "tag_id"
529 539 t.integer "taggable_id"
... ...
debian/changelog
  1 +noosfero (0.45.1) unstable; urgency=low
  2 +
  3 + * Bugfix release
  4 +
  5 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Tue, 07 Jan 2014 14:12:53 +0000
  6 +
1 7 noosfero (0.45.0) unstable; urgency=low
2 8  
3 9 * New features release
... ...
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.45.0'
  6 + VERSION = '0.45.1'
7 7  
8 8 def self.pattern_for_controllers_in_directory(dir)
9 9 disjunction = controllers_in_directory(dir).join('|')
... ...
lib/noosfero/gravatar.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +module Noosfero::Gravatar
  2 + def gravatar_profile_image_url(email, options = {})
  3 + "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(email.to_s)}?" + {
  4 + :only_path => false,
  5 + }.merge(options).map{|k,v| '%s=%s' % [ k,v ] }.join('&')
  6 + end
  7 +
  8 + def gravatar_profile_url(email)
  9 + 'http://www.gravatar.com/'+ Digest::MD5.hexdigest(email.to_s)
  10 + end
  11 +end
... ...
lib/noosfero/plugin.rb
... ... @@ -57,6 +57,9 @@ class Noosfero::Plugin
57 57 path << File.join(dir, 'lib')
58 58 end
59 59  
  60 + # add view path
  61 + ActionController::Base.view_paths.unshift(File.join(dir, 'views'))
  62 +
60 63 # load vendor/plugins
61 64 Dir.glob(File.join(dir, '/vendor/plugins/*')).each do |vendor_plugin|
62 65 [ ActiveSupport::Dependencies.load_paths, $:].each{ |path| path << "#{vendor_plugin}/lib" }
... ...
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
... ... @@ -13,7 +13,7 @@
13 13 <%= render :partial => 'shared/form_submission', :locals => {:f => f} %>
14 14  
15 15 <% button_bar do %>
16   - <%= submit_button :save, _('Save'), :cancel => {:action => 'index'} %>
  16 + <%= submit_button :save, _('Save'), :cancel => {:controller=>:profile, :profile => profile.identifier} %>
17 17 <% end %>
18 18 <% end %>
19 19 <% else %>
... ...
public/designs/themes/base/style.css
... ... @@ -89,7 +89,7 @@ body, th, td, input {
89 89 color: #555753;
90 90 }
91 91  
92   -#controlpanel, #logout, #openchat, .manage-groups {
  92 +#user .logged-in > * {
93 93 margin-left: 25px;
94 94 }
95 95  
... ... @@ -105,6 +105,14 @@ body, th, td, input {
105 105 top: 3px;
106 106 }
107 107  
  108 +#user #homepage-link i {
  109 + width: 18px;
  110 + height: 18px;
  111 + left: -20px;
  112 + top: -2px;
  113 + background-position: 50% 50%;
  114 +}
  115 +
108 116 #user form {
109 117 position: relative;
110 118 display: inline;
... ...
public/javascripts/application.js
... ... @@ -539,7 +539,11 @@ jQuery(function($) {
539 539 }
540 540 $(this).attr('href', new_href);
541 541 });
542   - var html = $(this).html().replace(/{login}/g, data.login).replace('{month}', data.since_month).replace('{year}', data.since_year);
  542 + var html = $(this).html()
  543 + .replace(/{login}/g, data.login)
  544 + .replace('{avatar}', data.avatar)
  545 + .replace('{month}', data.since_month)
  546 + .replace('{year}', data.since_year);
543 547 $(this).html(html).fadeIn();
544 548 if (data.is_admin) {
545 549 $('#user .admin-link').show();
... ...
public/stylesheets/application.css
... ... @@ -286,10 +286,10 @@ div.pending-tasks {
286 286 border: 1px solid #BFC2BC;
287 287 margin-bottom: 20px;
288 288 }
289   -#pending-tasks-count {
  289 +#user .logged-in #pending-tasks-count {
290 290 padding-left: 5px;
291 291 padding-right: 5px;
292   - margin-left: 2px;
  292 + margin-left: 3px;
293 293 text-decoration: none;
294 294 background-color: #F57900;
295 295 -moz-border-radius: 2px;
... ... @@ -871,7 +871,10 @@ code input {
871 871 }
872 872 #manage-enterprises .simplemenu-item a {
873 873 background-repeat: no-repeat;
874   - padding-left: 20px;
  874 + background-position: 5px 50%;
  875 + padding: 1px 0px 0px 26px;
  876 + line-height: 15px;
  877 + display: block;
875 878 }
876 879 #manage-enterprises .simplemenu-item a span {
877 880 display: none;
... ... @@ -1287,6 +1290,7 @@ a.comment-picture {
1287 1290 .scrap-replies {
1288 1291 border: 1px solid #fff;
1289 1292 padding: 0;
  1293 + border-right: 0px;
1290 1294 -moz-border-radius: 4px;
1291 1295 -webkit-border-radius: 4px;
1292 1296 border-radius: 4px;
... ... @@ -5571,7 +5575,7 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5571 5575  
5572 5576 #profile-wall ul.profile-wall-activities-comments ul,
5573 5577 #profile-network ul.profile-wall-activities-comments ul {
5574   - padding-left: 0px;
  5578 + padding-left: 12px;
5575 5579 }
5576 5580  
5577 5581 #profile-wall .profile-wall-activities-comments li,
... ...
test/functional/application_controller_test.rb
... ... @@ -500,4 +500,46 @@ class ApplicationControllerTest &lt; ActionController::TestCase
500 500 end
501 501  
502 502 end
  503 +
  504 + should 'do not duplicate plugin filters' do
  505 +
  506 + class FilterPlugin < Noosfero::Plugin
  507 + def test_controller_filters
  508 + { :type => 'before_filter',
  509 + :method_name => 'filter_plugin',
  510 + :options => {:only => 'some_method'},
  511 + :block => lambda {} }
  512 + end
  513 + end
  514 +
  515 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([FilterPlugin.new])
  516 +
  517 + get :index
  518 + get :index
  519 + assert_equal 1, @controller.class.filter_chain.select{|c| c.method == 'application_controller_test_filter_plugin_filter_plugin'}.count
  520 + end
  521 +
  522 + should 'do not call plugin filter block on a environment that this plugin is not enabled' do
  523 +
  524 + class OtherFilterPlugin < Noosfero::Plugin
  525 + def test_controller_filters
  526 + { :type => 'before_filter',
  527 + :method_name => 'filter_plugin',
  528 + :options => {:only => 'some_method'},
  529 + :block => lambda {'plugin block called'} }
  530 + end
  531 + end
  532 +
  533 + environment1 = fast_create(Environment, :name => 'test environment')
  534 + environment1.enable_plugin(OtherFilterPlugin.name)
  535 + environment2 = fast_create(Environment, :name => 'other test environment')
  536 +
  537 + @controller.stubs(:environment).returns(environment1)
  538 + get :index
  539 + assert_equal 'plugin block called', @controller.application_controller_test_other_filter_plugin_filter_plugin
  540 +
  541 + @controller.stubs(:environment).returns(environment2)
  542 + assert_equal nil, @controller.application_controller_test_other_filter_plugin_filter_plugin
  543 + end
  544 +
503 545 end
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -600,6 +600,29 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
600 600 assert_equal 2, assigns(:images).size
601 601 end
602 602  
  603 + should 'not display private images in the slideshow for unauthorized people' do
  604 + owner = create_user('owner').person
  605 + unauthorized = create_user('unauthorized').person
  606 + folder = Gallery.create!(:name => 'gallery', :profile => owner)
  607 + image1 = UploadedFile.create!(:profile => owner, :parent => folder, :uploaded_data => fixture_file_upload('/files/other-pic.jpg', 'image/jpg'), :published => false)
  608 + login_as('unauthorized')
  609 + get :view_page, :profile => owner.identifier, :page => folder.explode_path, :slideshow => true
  610 + assert_response :success
  611 + assert_equal 0, assigns(:images).length
  612 + end
  613 +
  614 + should 'not display private images thumbnails for unauthorized people' do
  615 + owner = create_user('owner').person
  616 + unauthorized = create_user('unauthorized').person
  617 + folder = Gallery.create!(:name => 'gallery', :profile => owner)
  618 + image1 = UploadedFile.create!(:profile => owner, :parent => folder, :uploaded_data => fixture_file_upload('/files/other-pic.jpg', 'image/jpg'), :published => false)
  619 + login_as('unauthorized')
  620 + get :view_page, :profile => owner.identifier, :page => folder.explode_path
  621 + assert_response :success
  622 + assert_select '.image-gallery-item', 0
  623 + end
  624 +
  625 +
603 626 should 'display default image in the slideshow if thumbnails were not processed' do
604 627 @controller.stubs(:per_page).returns(1)
605 628 folder = Gallery.create!(:name => 'gallery', :profile => profile)
... ...
test/unit/application_helper_test.rb
... ... @@ -466,32 +466,19 @@ class ApplicationHelperTest &lt; ActiveSupport::TestCase
466 466 assert_match(/Community nick/, page_title)
467 467 end
468 468  
469   - should 'generate a gravatar image url' do
470   - stubs(:environment).returns(Environment.default)
471   - @controller = ApplicationController.new
472   -
  469 + should 'gravatar default parameter' do
  470 + profile = mock
  471 + profile.stubs(:theme).returns('some-theme')
  472 + stubs(:profile).returns(profile)
473 473 with_constants :NOOSFERO_CONF => {'gravatar' => 'crazyvatar'} do
474   - url = str_gravatar_url_for( 'rms@gnu.org', :size => 50 )
475   - assert_match(/^http:\/\/www\.gravatar\.com\/avatar\.php\?/, url)
476   - assert_match(/(\?|&)gravatar_id=ed5214d4b49154ba0dc397a28ee90eb7(&|$)/, url)
477   - assert_match(/(\?|&)d=crazyvatar(&|$)/, url)
478   - assert_match(/(\?|&)size=50(&|$)/, url)
  474 + assert_equal gravatar_default, 'crazyvatar'
479 475 end
480 476 stubs(:theme_option).returns('gravatar' => 'nicevatar')
481 477 with_constants :NOOSFERO_CONF => {'gravatar' => 'crazyvatar'} do
482   - url = str_gravatar_url_for( 'rms@gnu.org', :size => 50 )
483   - assert_match(/^http:\/\/www\.gravatar\.com\/avatar\.php\?/, url)
484   - assert_match(/(\?|&)gravatar_id=ed5214d4b49154ba0dc397a28ee90eb7(&|$)/, url)
485   - assert_match(/(\?|&)d=nicevatar(&|$)/, url)
486   - assert_match(/(\?|&)size=50(&|$)/, url)
  478 + assert_equal gravatar_default, 'nicevatar'
487 479 end
488 480 end
489 481  
490   - should 'generate a gravatar profile url' do
491   - url = gravatar_profile_url( 'rms@gnu.org' )
492   - assert_equal('http://www.gravatar.com/ed5214d4b49154ba0dc397a28ee90eb7', url)
493   - end
494   -
495 482 should 'use theme passed via param when in development mode' do
496 483 stubs(:environment).returns(Environment.new(:theme => 'environment-theme'))
497 484 ENV.stubs(:[]).with('RAILS_ENV').returns('development')
... ...
test/unit/gravatar_test.rb 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class GravatarTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @object = Object.new
  7 + @object.extend(Noosfero::Gravatar)
  8 + end
  9 +
  10 + should 'generate a gravatar image url' do
  11 + url = @object.gravatar_profile_image_url( 'rms@gnu.org', :size => 50, :d => 'crazyvatar' )
  12 + assert_match(/^http:\/\/www\.gravatar\.com\/avatar\/ed5214d4b49154ba0dc397a28ee90eb7?/, url)
  13 + assert_match(/(\?|&)d=crazyvatar(&|$)/, url)
  14 + assert_match(/(\?|&)size=50(&|$)/, url)
  15 +
  16 + url = @object.gravatar_profile_image_url( 'rms@gnu.org', :size => 50, :d => 'nicevatar' )
  17 + assert_match(/^http:\/\/www\.gravatar\.com\/avatar\/ed5214d4b49154ba0dc397a28ee90eb7?/, url)
  18 + assert_match(/(\?|&)d=nicevatar(&|$)/, url)
  19 + assert_match(/(\?|&)size=50(&|$)/, url)
  20 + end
  21 +
  22 + should 'generate a gravatar profile url' do
  23 + url = @object.gravatar_profile_url( 'rms@gnu.org' )
  24 + assert_equal('http://www.gravatar.com/ed5214d4b49154ba0dc397a28ee90eb7', url)
  25 + end
  26 +end
... ...
test/unit/person_test.rb
... ... @@ -1393,4 +1393,24 @@ class PersonTest &lt; ActiveSupport::TestCase
1393 1393 assert_not_includes user.memberships_by_role(member_role), c1
1394 1394 end
1395 1395  
  1396 + should 'not list leave_scrap_to_self in activities' do
  1397 + person = fast_create(Person)
  1398 + at = ActionTracker::Record.create!(:user => person, :verb => 'leave_scrap_to_self')
  1399 + person.reload
  1400 + assert_equal person.activities, []
  1401 + end
  1402 +
  1403 + should 'not list add_member_in_community in activities' do
  1404 + person = fast_create(Person)
  1405 + at = ActionTracker::Record.create!(:user => person, :verb => 'add_member_in_community')
  1406 + person.reload
  1407 + assert_equal person.activities, []
  1408 + end
  1409 +
  1410 + should 'not list reply_scrap_on_self in activities' do
  1411 + person = fast_create(Person)
  1412 + at = ActionTracker::Record.create!(:user => person, :verb => 'reply_scrap_on_self')
  1413 + person.reload
  1414 + assert_equal person.activities, []
  1415 + end
1396 1416 end
... ...
test/unit/scrap_test.rb
... ... @@ -232,6 +232,14 @@ class ScrapTest &lt; ActiveSupport::TestCase
232 232 assert_equal s, s2.root
233 233 end
234 234  
  235 + should "have the top_root defined" do
  236 + s = fast_create(Scrap)
  237 + s1 = fast_create(Scrap, :scrap_id => s.id)
  238 + s2 = fast_create(Scrap, :scrap_id => s1.id)
  239 + assert_equal s, s1.top_root
  240 + assert_equal s, s2.top_root
  241 + end
  242 +
235 243 should 'strip all html tags' do
236 244 s, r = fast_create(Person), fast_create(Person)
237 245 s = Scrap.new :sender => s, :receiver => r, :content => "<p>Test <b>Rails</b></p>"
... ... @@ -276,4 +284,14 @@ class ScrapTest &lt; ActiveSupport::TestCase
276 284 assert_equal s.scrap_wall_url, s.receiver.wall_url
277 285 end
278 286  
  287 + should 'create activity with reply_scrap_on_self when top_root scrap receiver is the same as sender' do
  288 + s, r = fast_create(Person), fast_create(Person)
  289 + root = fast_create(Scrap, :sender_id => s.id, :receiver_id => r.id)
  290 + assert_difference ActionTracker::Record, :count, 1 do
  291 + reply = Scrap.create!(:sender => r, :receiver => s, :scrap_id => root.id, :content => 'sample')
  292 + end
  293 + activity = ActionTracker::Record.last
  294 + assert_equal 'reply_scrap_on_self', activity.verb.to_s
  295 + end
  296 +
279 297 end
... ...
test/unit/user_test.rb
... ... @@ -336,10 +336,22 @@ class UserTest &lt; ActiveSupport::TestCase
336 336 Person.any_instance.stubs(:is_admin?).returns(true)
337 337 Person.any_instance.stubs(:created_at).returns(DateTime.parse('16-08-2010'))
338 338 expected_hash = {
339   - 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8, 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil, 'amount_of_friends' => 0,
  339 + 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8,
  340 + 'chat_enabled' => false, 'since_year' => 2010, 'avatar' =>
  341 + 'http://www.gravatar.com/avatar/a0517761d5125820c28d87860bc7c02e?only_path=false&d=&size=20',
  342 + 'email_domain' => nil, 'amount_of_friends' => 0,
340 343 'friends_list' => {}, 'enterprises' => [],
341 344 }
342   - assert_equal expected_hash, person.user.data_hash
  345 +
  346 + assert_equal expected_hash['login'], person.user.data_hash['login']
  347 + assert_equal expected_hash['is_admin'], person.user.data_hash['is_admin']
  348 + assert_equal expected_hash['since_month'], person.user.data_hash['since_month']
  349 + assert_equal expected_hash['chat_enabled'], person.user.data_hash['chat_enabled']
  350 + assert_equal expected_hash['since_year'], person.user.data_hash['since_year']
  351 + assert_equal expected_hash['avatar'], person.user.data_hash['avatar']
  352 + assert_equal expected_hash['email_domain'], person.user.data_hash['email_domain']
  353 + assert_equal expected_hash['amount_of_friends'], person.user.data_hash['amount_of_friends']
  354 + assert_equal expected_hash['friends_list'], person.user.data_hash['friends_list']
343 355 end
344 356  
345 357 should "data_hash return the friends_list information" do
... ...
vendor/plugins/noosfero_caching/init.rb
... ... @@ -62,7 +62,6 @@ end
62 62  
63 63 unless Rails.env.development?
64 64 middleware = ActionController::Dispatcher.middleware
65   - cookies_mw = ActionController::Session::CookieStore
66 65 ActionController::Base.send(:include, NoosferoHttpCaching)
67   - middleware.insert_before(cookies_mw, NoosferoHttpCaching::Middleware)
  66 + middleware.use NoosferoHttpCaching::Middleware
68 67 end
... ...