Commit 11dfb86bf56dd6ce8784ab13682b46a96f9efc2f

Authored by Rodrigo Souto
2 parents d442dac2 ec0f8b0e

Merge branch 'master' of gitlab.com:noosfero/noosfero

Showing 174 changed files with 2162 additions and 2196 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 174 files displayed.

@@ -11,7 +11,6 @@ gem 'will_paginate', '~> 3.0.3' @@ -11,7 +11,6 @@ gem 'will_paginate', '~> 3.0.3'
11 gem 'ruby-feedparser', '~> 0.7' 11 gem 'ruby-feedparser', '~> 0.7'
12 gem 'daemons', '~> 1.1.5' 12 gem 'daemons', '~> 1.1.5'
13 gem 'thin', '~> 1.3.1' 13 gem 'thin', '~> 1.3.1'
14 -gem 'hpricot', '~> 0.8.6'  
15 gem 'nokogiri', '~> 1.5.5' 14 gem 'nokogiri', '~> 1.5.5'
16 gem 'rake', :require => false 15 gem 'rake', :require => false
17 gem 'rest-client', '~> 1.6.7' 16 gem 'rest-client', '~> 1.6.7'
@@ -41,9 +40,12 @@ group :cucumber do @@ -41,9 +40,12 @@ group :cucumber do
41 gem 'selenium-webdriver', '~> 2.39.0' 40 gem 'selenium-webdriver', '~> 2.39.0'
42 end 41 end
43 42
  43 +# Requires custom dependencies
  44 +eval(File.read('config/Gemfile'), binding) rescue nil
  45 +
44 # include gemfiles from enabled plugins 46 # include gemfiles from enabled plugins
45 # plugins in baseplugins/ are not included on purpose. They should not have any 47 # plugins in baseplugins/ are not included on purpose. They should not have any
46 # dependencies. 48 # dependencies.
47 Dir.glob('config/plugins/*/Gemfile').each do |gemfile| 49 Dir.glob('config/plugins/*/Gemfile').each do |gemfile|
48 eval File.read(gemfile) 50 eval File.read(gemfile)
49 -end 51 -end
  52 +end
50 \ No newline at end of file 53 \ No newline at end of file
@@ -21,7 +21,7 @@ Noosfero is written in Ruby with the "[Rails framework](http://www.rubyonrails.o @@ -21,7 +21,7 @@ Noosfero is written in Ruby with the "[Rails framework](http://www.rubyonrails.o
21 You need to install some packages Noosfero depends on. On Debian GNU/Linux or Debian-based systems, all of these packages are available through the Debian archive. You can install them with the following command: 21 You need to install some packages Noosfero depends on. On Debian GNU/Linux or Debian-based systems, all of these packages are available through the Debian archive. You can install them with the following command:
22 22
23 # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 \ 23 # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 \
24 - libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libhpricot-ruby \ 24 + libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby \
25 libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin \ 25 libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin \
26 tango-icon-theme 26 tango-icon-theme
27 27
@@ -40,7 +40,6 @@ On other systems, they may or may not be available through your regular package @@ -40,7 +40,6 @@ On other systems, they may or may not be available through your regular package
40 * Daemons - http://daemons.rubyforge.org 40 * Daemons - http://daemons.rubyforge.org
41 * Thin: http://code.macournoyer.com/thin 41 * Thin: http://code.macournoyer.com/thin
42 * tango-icon-theme: http://tango.freedesktop.org/Tango_Icon_Library 42 * tango-icon-theme: http://tango.freedesktop.org/Tango_Icon_Library
43 -* Hpricot: http://hpricot.com  
44 43
45 If you manage to install Noosfero successfully on other systems than Debian, 44 If you manage to install Noosfero successfully on other systems than Debian,
46 please feel free to contact the Noosfero development mailing with the 45 please feel free to contact the Noosfero development mailing with the
INSTALL.multitenancy.md
@@ -26,7 +26,7 @@ The file config/database.yml must follow a structure in order to achieve multite @@ -26,7 +26,7 @@ The file config/database.yml must follow a structure in order to achieve multite
26 26
27 Each "hosted" environment must have an entry like this: 27 Each "hosted" environment must have an entry like this:
28 28
29 - env1_production: 29 + env1_production: &DEFAULT
30 adapter: postgresql 30 adapter: postgresql
31 encoding: unicode 31 encoding: unicode
32 database: noosfero 32 database: noosfero
@@ -61,7 +61,7 @@ The "hosted" environments define, besides the `schema_search_path`, a list of do @@ -61,7 +61,7 @@ The "hosted" environments define, besides the `schema_search_path`, a list of do
61 You must also tell the application which is the default environment. 61 You must also tell the application which is the default environment.
62 62
63 production: 63 production:
64 - env1_production 64 + <<: *DEFAULT
65 65
66 On the example above there are only three hosted environments, but it can be more than three. The schemas `env2` and `env3` must already exist in the same database of the hosting environment. As postgres user, you can create them typing: 66 On the example above there are only three hosted environments, but it can be more than three. The schemas `env2` and `env3` must already exist in the same database of the hosting environment. As postgres user, you can create them typing:
67 67
app/controllers/application_controller.rb
@@ -28,6 +28,7 @@ class ApplicationController &lt; ActionController::Base @@ -28,6 +28,7 @@ class ApplicationController &lt; ActionController::Base
28 unless environment.access_control_allow_methods.blank? 28 unless environment.access_control_allow_methods.blank?
29 response.headers["Access-Control-Allow-Methods"] = environment.access_control_allow_methods 29 response.headers["Access-Control-Allow-Methods"] = environment.access_control_allow_methods
30 end 30 end
  31 + response.headers["Access-Control-Allow-Credentials"] = 'true'
31 elsif environment.restrict_to_access_control_origins 32 elsif environment.restrict_to_access_control_origins
32 render_access_denied _('Origin not in allowed.') 33 render_access_denied _('Origin not in allowed.')
33 end 34 end
app/helpers/application_helper.rb
@@ -8,11 +8,7 @@ module ApplicationHelper @@ -8,11 +8,7 @@ module ApplicationHelper
8 8
9 include PermissionNameHelper 9 include PermissionNameHelper
10 10
11 - include LightboxHelper  
12 -  
13 - include ThickboxHelper  
14 -  
15 - include ColorboxHelper 11 + include ModalHelper
16 12
17 include BoxesHelper 13 include BoxesHelper
18 14
@@ -651,8 +647,8 @@ module ApplicationHelper @@ -651,8 +647,8 @@ module ApplicationHelper
651 ' onfocus="if(this.value==\''+s+'\'){this.value=\'\'} this.form.className=\'focus-in\'"'+ 647 ' onfocus="if(this.value==\''+s+'\'){this.value=\'\'} this.form.className=\'focus-in\'"'+
652 ' onblur="if(/^\s*$/.test(this.value)){this.value=\''+s+'\'} this.form.className=\'focus-out\'">'+ 648 ' onblur="if(/^\s*$/.test(this.value)){this.value=\''+s+'\'} this.form.className=\'focus-out\'">'+
653 '</form>' 649 '</form>'
654 - else #opt == 'lightbox_link' is default  
655 - lightbox_link_to '<span class="icon-menu-search"></span>'+ _('Search'), { 650 + else
  651 + modal_link_to '<span class="icon-menu-search"></span>'+ _('Search'), {
656 :controller => 'search', 652 :controller => 'search',
657 :action => 'popup', 653 :action => 'popup',
658 :category_path => (@category ? @category.explode_path : nil)}, 654 :category_path => (@category ? @category.explode_path : nil)},
@@ -1050,7 +1046,7 @@ module ApplicationHelper @@ -1050,7 +1046,7 @@ module ApplicationHelper
1050 {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}} 1046 {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}}
1051 ] 1047 ]
1052 if logged_in? 1048 if logged_in?
1053 - links.push(_('New content') => colorbox_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})})) 1049 + links.push(_('New content') => modal_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})}))
1054 end 1050 end
1055 1051
1056 link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => nil}, :id => 'submenu-contents') + 1052 link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => nil}, :id => 'submenu-contents') +
@@ -1398,16 +1394,16 @@ module ApplicationHelper @@ -1398,16 +1394,16 @@ module ApplicationHelper
1398 end 1394 end
1399 1395
1400 def convert_macro(html, source) 1396 def convert_macro(html, source)
1401 - doc = Hpricot(html) 1397 + doc = Nokogiri::HTML.fragment html
1402 #TODO This way is more efficient but do not support macro inside of 1398 #TODO This way is more efficient but do not support macro inside of
1403 # macro. You must parse them from the inside-out in order to enable 1399 # macro. You must parse them from the inside-out in order to enable
1404 # that. 1400 # that.
1405 - doc.search('.macro').each do |macro| 1401 + doc.css('.macro').each do |macro|
1406 macro_name = macro['data-macro'] 1402 macro_name = macro['data-macro']
1407 result = @plugins.parse_macro(macro_name, macro, source) 1403 result = @plugins.parse_macro(macro_name, macro, source)
1408 macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result 1404 macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result
1409 end 1405 end
1410 - doc.html 1406 + doc.to_html
1411 end 1407 end
1412 1408
1413 def default_folder_for_image_upload(profile) 1409 def default_folder_for_image_upload(profile)
app/helpers/boxes_helper.rb
@@ -231,7 +231,7 @@ module BoxesHelper @@ -231,7 +231,7 @@ module BoxesHelper
231 end 231 end
232 232
233 if block.editable? 233 if block.editable?
234 - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) 234 + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
235 end 235 end
236 236
237 if !block.main? 237 if !block.main?
@@ -241,7 +241,7 @@ module BoxesHelper @@ -241,7 +241,7 @@ module BoxesHelper
241 end 241 end
242 242
243 if block.respond_to?(:help) 243 if block.respond_to?(:help)
244 - buttons << thickbox_inline_popup_icon(:help, _('Help on this block'), {}, "help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}") 244 + buttons << modal_inline_icon(:help, _('Help on this block'), {}, "#help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + modal_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}")
245 end 245 end
246 246
247 if block.embedable? 247 if block.embedable?
app/helpers/colorbox_helper.rb
@@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
1 -module ColorboxHelper  
2 -  
3 - def colorbox_close_button(text, options = {})  
4 - button(:close, text, '#', colorbox_options(options, :close))  
5 - end  
6 -  
7 - def colorbox_button(type, label, url, options = {})  
8 - button(type, label, url, colorbox_options(options))  
9 - end  
10 -  
11 - def colorbox_icon_button(type, label, url, options = {})  
12 - icon_button(type, label, url, colorbox_options(options))  
13 - end  
14 -  
15 - # options must be an HTML options hash as passed to link_to etc.  
16 - #  
17 - # returns a new hash with colorbox class added. Keeps existing classes.  
18 - def colorbox_options(options, type=nil)  
19 - the_class = 'colorbox'  
20 - the_class += "-#{type.to_s}" unless type.nil?  
21 - the_class << " #{options[:class]}" if options.has_key?(:class)  
22 - options.merge(:class => the_class)  
23 - end  
24 -  
25 -end  
app/helpers/comment_helper.rb
@@ -65,7 +65,7 @@ module CommentHelper @@ -65,7 +65,7 @@ module CommentHelper
65 65
66 def link_for_edit(comment) 66 def link_for_edit(comment)
67 if comment.can_be_updated_by?(user) 67 if comment.can_be_updated_by?(user)
68 - {:link => expirable_comment_link(comment, :edit, _('Edit'), url_for(:profile => profile.identifier, :controller => :comment, :action => :edit, :id => comment.id),:class => 'colorbox')} 68 + {:link => expirable_comment_link(comment, :edit, _('Edit'), url_for(:profile => profile.identifier, :controller => :comment, :action => :edit, :id => comment.id),:class => 'modal')}
69 end 69 end
70 end 70 end
71 71
app/helpers/layout_helper.rb
@@ -45,8 +45,6 @@ module LayoutHelper @@ -45,8 +45,6 @@ module LayoutHelper
45 standard_stylesheets = [ 45 standard_stylesheets = [
46 'application', 46 'application',
47 'search', 47 'search',
48 - 'thickbox',  
49 - 'lightbox',  
50 'colorbox', 48 'colorbox',
51 'selectordie', 49 'selectordie',
52 'inputosaurus', 50 'inputosaurus',
app/helpers/lightbox_helper.rb
@@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
1 -module LightboxHelper  
2 -  
3 - def lightbox_link_to(text, url, options = {})  
4 - link_to(text, url, lightbox_options(options))  
5 - end  
6 -  
7 - def lightbox_close_button(text, options = {})  
8 - button(:close, text, '#', lightbox_options(options, 'lbAction').merge(:rel => 'deactivate'))  
9 - end  
10 -  
11 - def lightbox_button(type, label, url, options = {})  
12 - button(type, label, url, lightbox_options(options))  
13 - end  
14 -  
15 - def lightbox_icon_button(type, label, url, options = {})  
16 - icon_button(type, label, url, lightbox_options(options))  
17 - end  
18 -  
19 - # options must be an HTML options hash as passed to link_to etc.  
20 - #  
21 - # returns a new hash with lightbox class added. Keeps existing classes.  
22 - def lightbox_options(options, lightbox_type = 'lbOn')  
23 - the_class = lightbox_type  
24 - the_class << " #{options[:class]}" if options.has_key?(:class)  
25 - options.merge(:class => the_class)  
26 - end  
27 -  
28 - def lightbox?  
29 - request.xhr?  
30 - end  
31 -  
32 - def lightbox_remote_button(type, label, url, options = {})  
33 - button(type, label, url, lightbox_options(options, 'remote-lbOn'))  
34 - end  
35 -  
36 -end  
app/helpers/modal_helper.rb 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +module ModalHelper
  2 +
  3 + def modal_inline_link_to title, url, selector, options = {}
  4 + link_to title, url, modal_options(options.merge(:inline => selector))
  5 + end
  6 +
  7 + def modal_inline_icon type, title, url, selector, options = {}
  8 + icon_button type, title, url, modal_options(options.merge(:inline => selector))
  9 + end
  10 +
  11 + def modal_link_to title, url, options = {}
  12 + link_to title, url, modal_options(options)
  13 + end
  14 +
  15 + def modal_close_link text, options = {}
  16 + link_to text, '#', modal_options(options, :close)
  17 + end
  18 +
  19 + def modal_close_button(text, options = {})
  20 + button :close, text, '#', modal_options(options, :close).merge(:rel => 'deactivate')
  21 + end
  22 +
  23 + def modal_button(type, label, url, options = {})
  24 + button type, label, url, modal_options(options)
  25 + end
  26 +
  27 + def modal_icon_button(type, label, url, options = {})
  28 + icon_button type, label, url, modal_options(options)
  29 + end
  30 +
  31 + # options must be an HTML options hash as passed to link_to etc.
  32 + #
  33 + # returns a new hash with modal class added. Keeps existing classes.
  34 + def modal_options(options, type=nil)
  35 + inline_selector = options.delete :inline
  36 + options[:onclick] = "return noosfero.modal.inline('#{inline_selector}')" if inline_selector
  37 +
  38 + classes = if inline_selector then '' else 'modal-toggle' end
  39 + classes += " modal-#{type.to_s}" if type.present?
  40 + classes << " #{options[:class]}" if options.has_key? :class
  41 + options.merge!(:class => classes)
  42 +
  43 + options
  44 + end
  45 +
  46 +end
app/helpers/thickbox_helper.rb
@@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
1 -module ThickboxHelper  
2 - def thickbox_inline_popup_link(title, url, id, options = {})  
3 - link_to(title, url_for(url) + "#TB_inline?height=300&width=500&inlineId=#{id}&modal=true", {:class => 'thickbox'}.merge(options))  
4 - end  
5 - def thickbox_inline_popup_icon(type, title, url, id, options = {})  
6 - icon_button(type, title, url_for(url) + "#TB_inline?height=300&width=500&inlineId=#{id}&modal=true", {:class => "thickbox"}.merge(options))  
7 - end  
8 - def thickbox_close_button(title)  
9 - button_to_function(:close, title, 'tb_remove();')  
10 - end  
11 -end  
app/models/article.rb
1 -require 'hpricot'  
2 1
3 class Article < ActiveRecord::Base 2 class Article < ActiveRecord::Base
4 3
@@ -707,7 +706,7 @@ class Article &lt; ActiveRecord::Base @@ -707,7 +706,7 @@ class Article &lt; ActiveRecord::Base
707 end 706 end
708 707
709 def first_paragraph 708 def first_paragraph
710 - paragraphs = Hpricot(to_html).search('p') 709 + paragraphs = Nokogiri::HTML.fragment(to_html).css('p')
711 paragraphs.empty? ? '' : paragraphs.first.to_html 710 paragraphs.empty? ? '' : paragraphs.first.to_html
712 end 711 end
713 712
@@ -729,8 +728,8 @@ class Article &lt; ActiveRecord::Base @@ -729,8 +728,8 @@ class Article &lt; ActiveRecord::Base
729 728
730 def body_images_paths 729 def body_images_paths
731 require 'uri' 730 require 'uri'
732 - Hpricot(self.body.to_s).search('img[@src]').collect do |i|  
733 - (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i.attributes['src'])).to_s : i.attributes['src'] 731 + Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i|
  732 + (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i['src'])).to_s : i['src']
734 end 733 end
735 end 734 end
736 735
@@ -767,8 +766,8 @@ class Article &lt; ActiveRecord::Base @@ -767,8 +766,8 @@ class Article &lt; ActiveRecord::Base
767 end 766 end
768 767
769 def first_image 768 def first_image
770 - img = Hpricot(self.lead.to_s).search('img[@src]').first || Hpricot(self.body.to_s).search('img').first  
771 - img.nil? ? '' : img.attributes['src'] 769 + img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  770 + img.nil? ? '' : img['src']
772 end 771 end
773 772
774 delegate :lat, :lng, :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true 773 delegate :lat, :lng, :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true
app/models/enterprise.rb
@@ -19,7 +19,8 @@ class Enterprise &lt; Organization @@ -19,7 +19,8 @@ class Enterprise &lt; Organization
19 has_many :inputs, :through => :products 19 has_many :inputs, :through => :products
20 has_many :production_costs, :as => :owner 20 has_many :production_costs, :as => :owner
21 21
22 - has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' 22 + has_many :favorite_enterprise_people
  23 + has_many :fans, through: :favorite_enterprise_people, source: :person
23 24
24 def product_categories 25 def product_categories
25 ProductCategory.by_enterprise(self) 26 ProductCategory.by_enterprise(self)
app/models/environment.rb
@@ -273,6 +273,7 @@ class Environment &lt; ActiveRecord::Base @@ -273,6 +273,7 @@ class Environment &lt; ActiveRecord::Base
273 settings_items :help_message_to_add_enterprise, :type => String, :default => '' 273 settings_items :help_message_to_add_enterprise, :type => String, :default => ''
274 settings_items :tip_message_enterprise_activation_question, :type => String, :default => '' 274 settings_items :tip_message_enterprise_activation_question, :type => String, :default => ''
275 275
  276 + settings_items :currency_iso_unit, :type => String, :default => 'USD'
276 settings_items :currency_unit, :type => String, :default => '$' 277 settings_items :currency_unit, :type => String, :default => '$'
277 settings_items :currency_separator, :type => String, :default => '.' 278 settings_items :currency_separator, :type => String, :default => '.'
278 settings_items :currency_delimiter, :type => String, :default => ',' 279 settings_items :currency_delimiter, :type => String, :default => ','
app/models/external_feed.rb
@@ -14,9 +14,9 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -14,9 +14,9 @@ class ExternalFeed &lt; ActiveRecord::Base
14 14
15 def add_item(title, link, date, content) 15 def add_item(title, link, date, content)
16 return if content.blank? 16 return if content.blank?
17 - doc = Hpricot(content)  
18 - doc.search('*').each do |p|  
19 - if p.instance_of? Hpricot::Elem 17 + doc = Nokogiri::HTML.fragment content
  18 + doc.css('*').each do |p|
  19 + if p.instance_of? Nokogiri::XML::Element
20 p.remove_attribute 'style' 20 p.remove_attribute 'style'
21 p.remove_attribute 'class' 21 p.remove_attribute 'class'
22 end 22 end
@@ -26,10 +26,10 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -26,10 +26,10 @@ class ExternalFeed &lt; ActiveRecord::Base
26 article = TinyMceArticle.new 26 article = TinyMceArticle.new
27 article.name = title 27 article.name = title
28 article.profile = blog.profile 28 article.profile = blog.profile
29 - article.body = content  
30 - article.published_at = date  
31 - article.source = link  
32 - article.profile = blog.profile 29 + article.body = content
  30 + article.published_at = date
  31 + article.source = link
  32 + article.profile = blog.profile
33 article.parent = blog 33 article.parent = blog
34 article.author_name = self.feed_title 34 article.author_name = self.feed_title
35 unless blog.children.exists?(:slug => article.slug) 35 unless blog.children.exists?(:slug => article.slug)
app/models/favorite_enterprise_person.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class FavoriteEnterprisePerson < ActiveRecord::Base
  2 +
  3 + self.table_name = :favorite_enteprises_people
  4 +
  5 + belongs_to :enterprise
  6 + belongs_to :person
  7 +
  8 +end
app/models/forum.rb
@@ -54,7 +54,7 @@ class Forum &lt; Folder @@ -54,7 +54,7 @@ class Forum &lt; Folder
54 54
55 def first_paragraph 55 def first_paragraph
56 return '' if body.blank? 56 return '' if body.blank?
57 - paragraphs = Hpricot(body).search('p') 57 + paragraphs = Nokogiri::HTML.fragment(body).css('p')
58 paragraphs.empty? ? '' : paragraphs.first.to_html 58 paragraphs.empty? ? '' : paragraphs.first.to_html
59 end 59 end
60 60
app/models/input.rb
1 class Input < ActiveRecord::Base 1 class Input < ActiveRecord::Base
2 2
3 - attr_accessible :product, :product_category, :product_category_id, :amount_used, :unit_id, :price_per_unit, :relevant_to_price 3 + attr_accessible :product, :product_id, :product_category, :product_category_id,
  4 + :amount_used, :unit_id, :price_per_unit, :relevant_to_price, :is_from_solidarity_economy
4 5
5 belongs_to :product 6 belongs_to :product
6 belongs_to :product_category 7 belongs_to :product_category
app/models/person_notifier.rb
@@ -22,12 +22,17 @@ class PersonNotifier @@ -22,12 +22,17 @@ class PersonNotifier
22 schedule_next_notification_mail 22 schedule_next_notification_mail
23 end 23 end
24 24
  25 + def notify_from
  26 + @person.last_notification || DateTime.now - @person.notification_time.hours
  27 + end
  28 +
25 def notify 29 def notify
26 if @person.notification_time && @person.notification_time > 0 30 if @person.notification_time && @person.notification_time > 0
27 - from = @person.last_notification || DateTime.now - @person.notification_time.hours  
28 - notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", from]) 31 + notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", notify_from])
  32 + tasks = Task.to(@person).without_spam.pending.where("created_at > ?", notify_from).order_by('created_at', 'asc')
  33 +
29 Noosfero.with_locale @person.environment.default_language do 34 Noosfero.with_locale @person.environment.default_language do
30 - Mailer::content_summary(@person, notifications).deliver unless notifications.empty? 35 + Mailer::content_summary(@person, notifications, tasks).deliver unless notifications.empty? && tasks.empty?
31 end 36 end
32 @person.settings[:last_notification] = DateTime.now 37 @person.settings[:last_notification] = DateTime.now
33 @person.save! 38 @person.save!
@@ -59,8 +64,12 @@ class PersonNotifier @@ -59,8 +64,12 @@ class PersonNotifier
59 end 64 end
60 65
61 def failure(job) 66 def failure(job)
62 - person = Person.find(person_id)  
63 - person.notifier.dispatch_notification_mail 67 + begin
  68 + person = Person.find(person_id)
  69 + person.notifier.dispatch_notification_mail
  70 + rescue
  71 + Rails.logger.error "PersonNotifier::NotifyJob: Cannot recover from failure"
  72 + end
64 end 73 end
65 74
66 end 75 end
@@ -73,18 +82,24 @@ class PersonNotifier @@ -73,18 +82,24 @@ class PersonNotifier
73 {:theme => nil} 82 {:theme => nil}
74 end 83 end
75 84
76 - def content_summary(person, notifications) 85 + def content_summary(person, notifications, tasks)
  86 + if person.environment
  87 + ActionMailer::Base.asset_host = person.environment.top_url
  88 + ActionMailer::Base.default_url_options[:host] = person.environment.default_hostname
  89 + end
  90 +
77 @current_theme = 'default' 91 @current_theme = 'default'
78 @profile = person 92 @profile = person
79 @recipient = @profile.nickname || @profile.name 93 @recipient = @profile.nickname || @profile.name
80 @notifications = notifications 94 @notifications = notifications
  95 + @tasks = tasks
81 @environment = @profile.environment.name 96 @environment = @profile.environment.name
82 @url = @profile.environment.top_url 97 @url = @profile.environment.top_url
83 mail( 98 mail(
84 content_type: "text/html", 99 content_type: "text/html",
85 from: "#{@profile.environment.name} <#{@profile.environment.noreply_email}>", 100 from: "#{@profile.environment.name} <#{@profile.environment.noreply_email}>",
86 to: @profile.email, 101 to: @profile.email,
87 - subject: _("[%s] Network Activity") % [@profile.environment.name] 102 + subject: _("[%s] Notifications") % [@profile.environment.name]
88 ) 103 )
89 end 104 end
90 end 105 end
app/models/product.rb
@@ -10,7 +10,8 @@ class Product &lt; ActiveRecord::Base @@ -10,7 +10,8 @@ class Product &lt; ActiveRecord::Base
10 :display => %w[full map] 10 :display => %w[full map]
11 } 11 }
12 12
13 - attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list 13 + attr_accessible :name, :product_category, :profile, :profile_id, :enterprise,
  14 + :highlighted, :price, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list
14 15
15 def self.default_search_display 16 def self.default_search_display
16 'full' 17 'full'
app/models/text_article.rb
1 require 'noosfero/translatable_content' 1 require 'noosfero/translatable_content'
2 2
3 -# a base class for all text article types. 3 +# a base class for all text article types.
4 class TextArticle < Article 4 class TextArticle < Article
5 5
6 xss_terminate :only => [ :name ], :on => 'validation' 6 xss_terminate :only => [ :name ], :on => 'validation'
@@ -26,10 +26,10 @@ class TextArticle &lt; Article @@ -26,10 +26,10 @@ class TextArticle &lt; Article
26 before_save :set_relative_path 26 before_save :set_relative_path
27 27
28 def set_relative_path 28 def set_relative_path
29 - parsed = Hpricot(self.body.to_s)  
30 - parsed.search('img[@src]').map { |i| change_element_path(i, 'src') }  
31 - parsed.search('a[@href]').map { |i| change_element_path(i, 'href') }  
32 - self.body = parsed.to_s 29 + parsed = Nokogiri::HTML.fragment(self.body.to_s)
  30 + parsed.css('img[src]').each { |i| change_element_path(i, 'src') }
  31 + parsed.css('a[href]').each { |i| change_element_path(i, 'href') }
  32 + self.body = parsed.to_html
33 end 33 end
34 34
35 def change_element_path(el, attribute) 35 def change_element_path(el, attribute)
app/models/user.rb
@@ -54,7 +54,7 @@ class User &lt; ActiveRecord::Base @@ -54,7 +54,7 @@ class User &lt; ActiveRecord::Base
54 54
55 user.person = p 55 user.person = p
56 end 56 end
57 - if user.environment.enabled?('skip_new_user_email_confirmation') 57 + if user.environment.enabled?('skip_new_user_email_confirmation')
58 if user.environment.enabled?('admin_must_approve_new_users') 58 if user.environment.enabled?('admin_must_approve_new_users')
59 create_moderate_task 59 create_moderate_task
60 else 60 else
@@ -102,6 +102,7 @@ class User &lt; ActiveRecord::Base @@ -102,6 +102,7 @@ class User &lt; ActiveRecord::Base
102 validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) 102 validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?})
103 validates_uniqueness_of :login, :email, :case_sensitive => false, :scope => :environment_id 103 validates_uniqueness_of :login, :email, :case_sensitive => false, :scope => :environment_id
104 before_save :encrypt_password 104 before_save :encrypt_password
  105 + before_save :normalize_email, if: proc{ |u| u.email.present? }
105 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?}) 106 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?})
106 107
107 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n 108 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n
@@ -114,6 +115,10 @@ class User &lt; ActiveRecord::Base @@ -114,6 +115,10 @@ class User &lt; ActiveRecord::Base
114 u && u.authenticated?(password) ? u : nil 115 u && u.authenticated?(password) ? u : nil
115 end 116 end
116 117
  118 + def register_login
  119 + self.update_attribute :last_login_at, Time.now
  120 + end
  121 +
117 # Activates the user in the database. 122 # Activates the user in the database.
118 def activate 123 def activate
119 return false unless self.person 124 return false unless self.person
@@ -332,6 +337,11 @@ class User &lt; ActiveRecord::Base @@ -332,6 +337,11 @@ class User &lt; ActiveRecord::Base
332 end 337 end
333 338
334 protected 339 protected
  340 +
  341 + def normalize_email
  342 + self.email = self.email.squish.downcase
  343 + end
  344 +
335 # before filter 345 # before filter
336 def encrypt_password 346 def encrypt_password
337 return if password.blank? 347 return if password.blank?
@@ -359,6 +369,6 @@ class User &lt; ActiveRecord::Base @@ -359,6 +369,6 @@ class User &lt; ActiveRecord::Base
359 369
360 def delay_activation_check 370 def delay_activation_check
361 return if person.is_template? 371 return if person.is_template?
362 - Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) 372 + Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => (NOOSFERO_CONF['hours_until_user_activation_check'] || 72).hours.from_now})
363 end 373 end
364 end 374 end
app/views/account/_login_form.html.erb
1 <%= labelled_form_for :user, 1 <%= labelled_form_for :user,
2 :url => { :controller => 'account', :action => (params[:enterprise_code] ? 'activate_enterprise' : 'login') } do |f| %> 2 :url => { :controller => 'account', :action => (params[:enterprise_code] ? 'activate_enterprise' : 'login') } do |f| %>
3 3
4 -<%= f.text_field :login,  
5 - :id => ( lightbox? ? 'lightbox_' : '' ) + 'user_login',  
6 - :onchange => 'this.value = convToValidLogin( this.value )' %> 4 +<%= f.text_field :login, :id => 'user_login', :onchange => 'this.value = convToValidLogin( this.value )' %>
7 5
8 -<%= f.password_field :password,  
9 - :id => ( lightbox? ? 'lightbox_' : '' ) + 'user_password' %> 6 +<%= f.password_field :password, :id => 'user_password' %>
10 7
11 <% if params[:enterprise_code] %> 8 <% if params[:enterprise_code] %>
12 <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %> 9 <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %>
@@ -16,7 +13,7 @@ @@ -16,7 +13,7 @@
16 13
17 <% button_bar do %> 14 <% button_bar do %>
18 <%= submit_button( 'login', _('Log in') )%> 15 <%= submit_button( 'login', _('Log in') )%>
19 - <%= lightbox_close_button(_('Cancel')) if lightbox? %> 16 + <%= modal_close_button _('Cancel') if request.xhr? %>
20 <% end %> 17 <% end %>
21 18
22 <% end %> 19 <% end %>
app/views/account/_signup_form.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <input type="hidden" id="signup_time_key" name="signup_time_key" /> 16 <input type="hidden" id="signup_time_key" name="signup_time_key" />
17 <script type="text/javascript"> 17 <script type="text/javascript">
18 jQuery.ajax({ 18 jQuery.ajax({
19 - type: "POST", 19 + type: "GET",
20 url: "<%= url_for :controller=>'account', :action=>'signup_time' %>", 20 url: "<%= url_for :controller=>'account', :action=>'signup_time' %>",
21 dataType: 'json', 21 dataType: 'json',
22 success: function(data) { 22 success: function(data) {
app/views/account/index_anonymous.html.erb
1 <h1><%= _('Identify yourself') %></h1> 1 <h1><%= _('Identify yourself') %></h1>
2 2
3 <p> 3 <p>
4 -<%= lightbox_link_to _('Login.'), { :controller => 'account', :action => 'login_popup' } %> 4 +<%= modal_link_to _('Login.'), { :controller => 'account', :action => 'login_popup' } %>
5 5
6 <%= _('You need to login to be able to use all the features in this environment.') %> 6 <%= _('You need to login to be able to use all the features in this environment.') %>
7 </p> 7 </p>
app/views/account/login.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <h2><%= _('Login') %></h2> 3 <h2><%= _('Login') %></h2>
4 4
5 <% @user ||= User.new %> 5 <% @user ||= User.new %>
6 -<% is_thickbox ||= false %> 6 +<% is_popin ||= false %>
7 7
8 <%= @message %> 8 <%= @message %>
9 9
@@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
17 17
18 <% button_bar do %> 18 <% button_bar do %>
19 <%= submit_button( 'login', _('Log in') )%> 19 <%= submit_button( 'login', _('Log in') )%>
20 - <% if is_thickbox %>  
21 - <%= thickbox_close_button(_('Cancel')) %> 20 + <% if is_popin %>
  21 + <%= modal_close_button(_('Cancel')) %>
22 <% end %> 22 <% end %>
23 <% end %> 23 <% end %>
24 24
app/views/account/logout_popup.html.erb
@@ -2,6 +2,6 @@ @@ -2,6 +2,6 @@
2 <p> 2 <p>
3 <% button_bar do %> 3 <% button_bar do %>
4 <%= button :ok, _('Yes'), { :controller => 'account', :action => 'logout' } %> 4 <%= button :ok, _('Yes'), { :controller => 'account', :action => 'logout' } %>
5 - <%= lightbox_close_button _('No, I want to stay.') %> 5 + <%= modal_close_button _('No, I want to stay.') %>
6 <% end %> 6 <% end %>
7 </p> 7 </p>
app/views/box_organizer/add_block.html.erb
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 42
43 <% button_bar do %> 43 <% button_bar do %>
44 <%= submit_button(:add, _("Add")) %> 44 <%= submit_button(:add, _("Add")) %>
45 - <%= colorbox_close_button(_('Close')) %> 45 + <%= modal_close_button(_('Close')) %>
46 <% end %> 46 <% end %>
47 47
48 <% end %> 48 <% end %>
app/views/box_organizer/edit.html.erb
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 27
28 <% button_bar do %> 28 <% button_bar do %>
29 <%= submit_button(:save, _('Save')) %> 29 <%= submit_button(:save, _('Save')) %>
30 - <%= colorbox_close_button(_('Cancel')) %> 30 + <%= modal_close_button(_('Cancel')) %>
31 <% end %> 31 <% end %>
32 32
33 <% end %> 33 <% end %>
app/views/box_organizer/index.html.erb
1 <h1><%= _('Editing sideboxes')%></h1> 1 <h1><%= _('Editing sideboxes')%></h1>
2 2
3 <% button_bar :class=>'design-menu' do %> 3 <% button_bar :class=>'design-menu' do %>
4 - <%= colorbox_button('add', _('Add a block'), { :action => 'add_block' }) %> 4 + <%= modal_button('add', _('Add a block'), { :action => 'add_block' }) %>
5 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> 5 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %>
6 <% end %> 6 <% end %>
app/views/cms/edit.html.erb
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 <% end %> 28 <% end %>
29 29
30 <div style='float: right'> 30 <div style='float: right'>
31 - <%= lightbox_button :help, _('Why categorize?'), :action => 'why_categorize' %> 31 + <%= modal_button :help, _('Why categorize?'), :action => 'why_categorize' %>
32 </div> 32 </div>
33 33
34 <%= select_categories(:article, _('Categorize your article')) %> 34 <%= select_categories(:article, _('Categorize your article')) %>
app/views/cms/select_article_type.html.erb
@@ -15,6 +15,6 @@ @@ -15,6 +15,6 @@
15 </ul> 15 </ul>
16 <br style="clear:both" /> 16 <br style="clear:both" />
17 17
18 -<%= colorbox_close_button(_('Cancel')) %> 18 +<%= modal_close_button(_('Cancel')) %>
19 19
20 </div> 20 </div>
app/views/cms/view.html.erb
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 <% button_bar(:style => 'margin-bottom: 1em;') do %> 17 <% button_bar(:style => 'margin-bottom: 1em;') do %>
18 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> 18 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %>
19 19
20 - <%= colorbox_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %> 20 + <%= modal_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %>
21 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %> 21 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %>
22 <% end %> 22 <% end %>
23 23
app/views/cms/why_categorize.html.erb
@@ -5,5 +5,5 @@ @@ -5,5 +5,5 @@
5 </p> 5 </p>
6 6
7 <% button_bar do %> 7 <% button_bar do %>
8 - <%= lightbox_close_button _('Close') %> 8 + <%= modal_close_button _('Close') %>
9 <% end %> 9 <% end %>
app/views/comment/_comment_form.html.erb
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 10 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
11 <% button_bar do %> 11 <% button_bar do %>
12 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> 12 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %>
13 - <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close()" %> 13 + <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %>
14 <% end %> 14 <% end %>
15 </div> 15 </div>
16 16
@@ -31,10 +31,10 @@ function check_captcha(button, confirm_action) { @@ -31,10 +31,10 @@ function check_captcha(button, confirm_action) {
31 return true; 31 return true;
32 <% else %> 32 <% else %>
33 jQuery('#recaptcha-container').show(); 33 jQuery('#recaptcha-container').show();
34 - jQuery.colorbox({ html: jQuery('#recaptcha-container').html(), maxWidth : '600px', maxHeight : '300px' }); 34 + noosfero.modal.inline('#recaptcha-container', {maxWidth :'600px', maxHeight : '300px' });
35 jQuery('#confirm-captcha').unbind('click'); 35 jQuery('#confirm-captcha').unbind('click');
36 jQuery('#confirm-captcha').bind('click', function() { 36 jQuery('#confirm-captcha').bind('click', function() {
37 - jQuery.colorbox.close(); 37 + noosfero.modal.close();
38 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val(); 38 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val();
39 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val(); 39 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val();
40 button.form.confirm.value = 'true'; 40 button.form.confirm.value = 'true';
@@ -88,7 +88,7 @@ function check_captcha(button, confirm_action) { @@ -88,7 +88,7 @@ function check_captcha(button, confirm_action) {
88 <% if !edition_mode %> 88 <% if !edition_mode %>
89 <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> 89 <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %>
90 <% else %> 90 <% else %>
91 - <%= button :cancel, _('Cancel'), '#', :onclick => "jQuery.colorbox.close();" %> 91 + <%= button :cancel, _('Cancel'), '#', :onclick => "noosfero.modal.close();" %>
92 <% end %> 92 <% end %>
93 <% end %> 93 <% end %>
94 <% end %> 94 <% end %>
app/views/content_viewer/_article_toolbar.html.erb
@@ -28,14 +28,14 @@ @@ -28,14 +28,14 @@
28 <%= expirable_button @page, :locale, content, url %> 28 <%= expirable_button @page, :locale, content, url %>
29 <% end %> 29 <% end %>
30 30
31 - <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new, @page) %> 31 + <%= modal_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new, @page) %>
32 <% end %> 32 <% end %>
33 33
34 <% if @page.accept_uploads? && @page.allow_create?(user) %> 34 <% if @page.accept_uploads? && @page.allow_create?(user) %>
35 <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload, @page)%> 35 <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload, @page)%>
36 <% end %> 36 <% end %>
37 37
38 - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %> 38 + <% if !@page.allow_create?(user) && profile.organization? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %>
39 <% content = content_tag( 'span', _('Suggest an article') ) %> 39 <% content = content_tag( 'span', _('Suggest an article') ) %>
40 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> 40 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %>
41 <% options = {:id => 'suggest-article-link'} %> 41 <% options = {:id => 'suggest-article-link'} %>
app/views/content_viewer/_comment_form.html.erb
@@ -7,10 +7,10 @@ function submit_comment_form(button) { @@ -7,10 +7,10 @@ function submit_comment_form(button) {
7 return true; 7 return true;
8 <% else %> 8 <% else %>
9 jQuery('#recaptcha-container').show(); 9 jQuery('#recaptcha-container').show();
10 - jQuery.colorbox({ inline : true, href : '#recaptcha-container', maxWidth : '600px', maxHeight : '300px' }); 10 + noosfero.modal.inline('#recaptcha-container', {maxWidth :'600px', maxHeight : '300px' });
11 jQuery('#confirm-captcha').unbind('click'); 11 jQuery('#confirm-captcha').unbind('click');
12 jQuery('#confirm-captcha').bind('click', function() { 12 jQuery('#confirm-captcha').bind('click', function() {
13 - jQuery.colorbox.close(); 13 + noosfero.modal.close();
14 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val(); 14 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val();
15 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val(); 15 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val();
16 button.form.confirm.value = 'true'; 16 button.form.confirm.value = 'true';
@@ -38,7 +38,7 @@ function submit_comment_form(button) { @@ -38,7 +38,7 @@ function submit_comment_form(button) {
38 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 38 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
39 <% button_bar do %> 39 <% button_bar do %>
40 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> 40 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %>
41 - <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close()" %> 41 + <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %>
42 <% end %> 42 <% end %>
43 </div> 43 </div>
44 44
app/views/layouts/_javascript.html.erb
1 <%= javascript_include_tag 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', 'jrails', 'rails.js', 1 <%= javascript_include_tag 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', 'jrails', 'rails.js',
2 -'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox',  
3 -'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate',  
4 -'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange',  
5 -'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow', 'select-or-die/_src/selectordie',  
6 -'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'application.js', 'inputosaurus.js', :cache => 'cache/application' %> 2 + 'jquery.cycle.all.min.js', 'jquery.colorbox-min.js',
  3 + 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate',
  4 + 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange',
  5 + 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'inputosaurus.js', 'select-or-die/_src/selectordie',
  6 + # noosfero libraries
  7 + 'application.js', 'modal.js',
  8 + 'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow',
  9 + :cache => 'cache/application' %>
7 10
8 <% language = FastGettext.locale %> 11 <% language = FastGettext.locale %>
9 <% %w{messages methods}.each do |type| %> 12 <% %w{messages methods}.each do |type| %>
app/views/layouts/_user.html.erb
@@ -7,11 +7,11 @@ @@ -7,11 +7,11 @@
7 </span> 7 </span>
8 <% else %> 8 <% else %>
9 <span class='not-logged-in'> 9 <span class='not-logged-in'>
10 - <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> 10 + <%= _("<span class='login'>%s</span>") % modal_inline_link_to('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, '#inlineLoginBox', :id => 'link_login') %>
11 <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %> 11 <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %>
12 12
13 <div id='inlineLoginBox' style='display: none;'> 13 <div id='inlineLoginBox' style='display: none;'>
14 - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> 14 + <%= render :file => 'account/login', :locals => { :is_popin => true } %>
15 </div> 15 </div>
16 16
17 <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> 17 <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
app/views/layouts/application-ng.html.erb
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 <%= yield :head %> 18 <%= yield :head %>
19 <%= 19 <%=
20 @plugins.dispatch(:head_ending).map do |content| 20 @plugins.dispatch(:head_ending).map do |content|
21 - if content.respond_to?(:call) then instance_exec(&content).html_safe else content.html_safe end 21 + if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
22 end.join("\n") 22 end.join("\n")
23 %> 23 %>
24 24
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 32
33 <%= 33 <%=
34 @plugins.dispatch(:body_beginning).map do |content| 34 @plugins.dispatch(:body_beginning).map do |content|
35 - if content.respond_to?(:call) then instance_exec(&content).html_safe else content.html_safe end 35 + if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
36 end.join("\n") 36 end.join("\n")
37 %> 37 %>
38 38
app/views/person_notifier/mailer/_comment.html.erb
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <span style="font-size: 12px;"><%= comment.title %></span><br/> 19 <span style="font-size: 12px;"><%= comment.title %></span><br/>
20 <% end %> 20 <% end %>
21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> 21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
22 - <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span> 22 + <span style="font-size: 8px; color: #929292"><%= time_ago_as_sentence(comment.created_at) %></span>
23 <br style="clear: both;" /> 23 <br style="clear: both;" />
24 24
25 <% unless comment.replies.blank? %> 25 <% unless comment.replies.blank? %>
app/views/person_notifier/mailer/_create_article.html.erb
1 -<table>  
2 <tr> 1 <tr>
3 - <td> 2 + <td style="width: 11%">
4 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 3 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5 </td> 4 </td>
6 <td> 5 <td>
7 - <p style="width:550px"> 6 + <p>
8 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
9 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> 8 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
10 - <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> 9 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
11 </p> 10 </p>
12 <p> 11 <p>
13 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> 12 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
@@ -24,4 +23,3 @@ @@ -24,4 +23,3 @@
24 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %> 23 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
25 </td> 24 </td>
26 </tr> 25 </tr>
27 -</table>  
app/views/person_notifier/mailer/_default_activity.html.erb
1 -<table>  
2 <tr> 1 <tr>
3 - <td> 2 + <td style="width: 11%">
4 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 3 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5 </td> 4 </td>
6 <td> 5 <td>
7 - <p style="width:550px"> 6 + <p>
8 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
9 - <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span> 8 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
10 </p> 9 </p>
11 </td> 10 </td>
12 </tr> 11 </tr>
@@ -16,4 +15,3 @@ @@ -16,4 +15,3 @@
16 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %> 15 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
17 </td> 16 </td>
18 </tr> 17 </tr>
19 -</table>  
app/views/person_notifier/mailer/_task.html.erb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<div style="border-bottom:1px solid #e2e2e2;padding:15px 0;width:600px">
  2 + <table style="width:100%;">
  3 + <tr>
  4 + <td style="width: 11%">
  5 + <%= profile_image(task.requestor, :minor) %>
  6 + </td>
  7 + <td>
  8 + <div>
  9 + <strong><%= link_to task.title, url_for(:controller => 'tasks', :profile => @profile.identifier, :action => 'index', :only_path => false) %></strong>
  10 + </div>
  11 + <div style="font-size: 14px">
  12 + <span style="font-size: 14px">
  13 + <%= task_information(task) %>
  14 + </span>
  15 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(task.created_at) %></span>
  16 + </div>
  17 + </td>
  18 + </tr>
  19 + </table>
  20 +</div>
app/views/person_notifier/mailer/_upload_image.html.erb
1 -<table>  
2 <tr> 1 <tr>
3 - <td> 2 + <td style="width: 11%">
4 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 3 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5 </td> 4 </td>
6 <td> 5 <td>
7 - <p style="width:550px"> 6 + <p>
8 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
9 - <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> 8 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
10 </p> 9 </p>
11 </td> 10 </td>
12 </tr> 11 </tr>
13 -</table>  
14 <div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div> 12 <div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
15 <br/> 13 <br/>
app/views/person_notifier/mailer/content_summary.html.erb
1 -<h3><%= _("%s's network activity") % @profile.name %></h3>  
2 -<br/>  
3 -<div>  
4 -<% @notifications.each do |activity| %>  
5 - <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px">  
6 - <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>  
7 - </div>  
8 -<% end %>  
9 -</div> 1 +<div style="background-color: #EEEEEE">
  2 + <table style="width: 100%;"><tbody><tr><td align="center">
  3 + <div style="display: table; background-color: white; margin: 26px 0;">
  4 + <div style="padding: 25px 20px 20px 20px;text-align: left;">
  5 + <%= link_to @url, :style => "text-decoration: none;" do %>
  6 + <span style="font-weight:bold;font-size: 28px;margin: 0;color: white;background-color: #AAAAAA;padding: 5px;"><%= @environment %></span>
  7 + <% end %>
  8 + <span style="font-weight:bold;color: #333;font-size:19px;margin-left: 8px;"><%= _("%s's Notifications") % @profile.name %></h3>
  9 + </div>
  10 + <div style="margin: 0 20px 20px 20px;border-top:1px solid #e2e2e2;">
  11 + <% if @tasks.present? %>
  12 + <div style="border-top: 1px solid #e2e2e2;">
  13 + <div style="border-bottom: 1px solid #CBCBCB;padding-top: 15px;font-weight: bold;text-align: right;color: #7c7c7c;float: right;min-width: 140px;">
  14 + <%= _('Tasks') %>
  15 + </div>
  16 + <%= render :partial => 'task', :collection => @tasks %>
  17 + </div>
  18 + <% end %>
  19 +
  20 + <% if @notifications.present? %>
  21 + <div style="border-top: 1px solid #e2e2e2;">
  22 + <div style="border-bottom: 1px solid #CBCBCB;padding-top: 15px;font-weight: bold;text-align: right;color: #7c7c7c;float: right;min-width: 140px;">
  23 + <%= _('Network Activity') %>
  24 + </div>
  25 + <% @notifications.each do |activity| %>
  26 + <div style="border-bottom:1px solid #e2e2e2;padding:15px 0;width:600px">
  27 + <table style="width:100%;">
  28 + <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>
  29 + </table>
  30 + </div>
  31 + <% end %>
  32 + </div>
  33 + <% end %>
10 34
11 -<div style="color:#444444;font-size:11px;">  
12 -<p><%= _("Greetings,") %></p>  
13 -<br/>  
14 -<p>--</p>  
15 -<p><%= _('%s team.') % @environment %></p>  
16 -<p><%= url_for @url %></p> 35 + <div style="color:#444444;font-size:11px;margin-bottom: 20px;">
  36 + <p style="margin:0"><%= _("Greetings,") %></p>
  37 + <p style="margin:0"><%= _('%s team.') % @environment %></p>
  38 + <p style="margin:0"><%= link_to @url, url_for(@url) %></p>
  39 + </div>
  40 + </div>
  41 + </td></tr></tbody></table>
17 </div> 42 </div>
18 -<br/>  
app/views/profile/join.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <%= hidden_field_tag(:confirmation, 1) %> 9 <%= hidden_field_tag(:confirmation, 1) %>
10 <%= submit_button(:ok, _("Yes, I want to join.") % profile.name) %> 10 <%= submit_button(:ok, _("Yes, I want to join.") % profile.name) %>
11 <% if logged_in? && request.xhr? %> 11 <% if logged_in? && request.xhr? %>
12 - <%= lightbox_close_button(_("No, I don't want")) %> 12 + <%= modal_close_button _("No, I don't want") %>
13 <% else %> 13 <% else %>
14 <%= button(:cancel, _("No, I don't want."), profile.url) %> 14 <%= button(:cancel, _("No, I don't want."), profile.url) %>
15 <% end %> 15 <% end %>
app/views/profile/leave.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <%= hidden_field_tag(:back_to, @back_to) %> 9 <%= hidden_field_tag(:back_to, @back_to) %>
10 <%= submit_button(:ok, _("Yes, I want to leave.") % profile.name) %> 10 <%= submit_button(:ok, _("Yes, I want to leave.") % profile.name) %>
11 <% if logged_in? && request.xhr? %> 11 <% if logged_in? && request.xhr? %>
12 - <%= lightbox_close_button(_("No, I don't want")) %> 12 + <%= modal_close_button _("No, I don't want") %>
13 <% else %> 13 <% else %>
14 <%= button(:cancel, _("No, I don't want."), profile.url) %> 14 <%= button(:cancel, _("No, I don't want."), profile.url) %>
15 <% end %> 15 <% end %>
app/views/profile/report_abuse.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <% end %> 9 <% end %>
10 10
11 <%= submit_button(:send, _('Report profile'), :style => 'float: left; cursor: pointer;', :id => 'report-abuse-submit-button', :onclick => "jQuery('#form-submit-loading').show()") %> 11 <%= submit_button(:send, _('Report profile'), :style => 'float: left; cursor: pointer;', :id => 'report-abuse-submit-button', :onclick => "jQuery('#form-submit-loading').show()") %>
12 - <%= button(:cancel, _('Cancel'), {}, :style => 'float: left; padding-top: 0px; padding-bottom: 0px;', :onclick => 'jQuery.colorbox.close(); return false;')%> 12 + <%= button(:cancel, _('Cancel'), {}, :style => 'float: left; padding-top: 0px; padding-bottom: 0px;', :onclick => 'noosfero.modal.close(); return false;')%>
13 <div id="form-submit-loading" class="small-loading" style="width: 16px; height: 16px; margin-top: 3px; float: left; display: none;"></div> 13 <div id="form-submit-loading" class="small-loading" style="width: 16px; height: 16px; margin-top: 3px; float: left; display: none;"></div>
14 <% end %> 14 <% end %>
15 15
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 success: function(data, status, ajax){ 30 success: function(data, status, ajax){
31 if ( !data.ok ) display_notice(data.error.message); 31 if ( !data.ok ) display_notice(data.error.message);
32 else { 32 else {
33 - $.colorbox.close(); 33 + noosfero.modal.close();
34 display_notice(data.message); 34 display_notice(data.message);
35 window.location.reload(); 35 window.location.reload();
36 } 36 }
app/views/profile_themes/add_css.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 5
6 <% button_bar do %> 6 <% button_bar do %>
7 <%= submit_button(:add, _('Add')) %> 7 <%= submit_button(:add, _('Add')) %>
8 - <%= lightbox_close_button(_('Cancel')) %> 8 + <%= modal_close_button _('Cancel') %>
9 <% end %> 9 <% end %>
10 10
11 <% end %> 11 <% end %>
app/views/profile_themes/edit.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <% end %> 16 <% end %>
17 </ul> 17 </ul>
18 <% button_bar do %> 18 <% button_bar do %>
19 - <%= lightbox_button(:add, _('New CSS'), :action => 'add_css', :id => @theme.id) %> 19 + <%= modal_button :add, _('New CSS'), :action => 'add_css', :id => @theme.id %>
20 <% end %> 20 <% end %>
21 </div> 21 </div>
22 22
@@ -25,10 +25,10 @@ @@ -25,10 +25,10 @@
25 <ul> 25 <ul>
26 <% for image in @image_files %> 26 <% for image in @image_files %>
27 <li><%= image_tag("/user_themes/#{@theme.id}/images/#{image}") %></li> 27 <li><%= image_tag("/user_themes/#{@theme.id}/images/#{image}") %></li>
28 - <% end %> 28 + <% end %>
29 </ul> 29 </ul>
30 <% button_bar do %> 30 <% button_bar do %>
31 - <%= lightbox_button(:add, _('Add image'), :action => 'add_image', :id => @theme.id) %> 31 + <%= modal_button :add, _('Add image'), :action => 'add_image', :id => @theme.id %>
32 <% end %> 32 <% end %>
33 </div> 33 </div>
34 34
app/views/profile_themes/index.html.erb
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 42
43 <% button_bar do %> 43 <% button_bar do %>
44 <% if environment.enabled?('user_themes') %> 44 <% if environment.enabled?('user_themes') %>
45 - <%= lightbox_button(:add, _('New theme ...'), :action => 'new') %> 45 + <%= modal_button :add, _('New theme ...'), :action => 'new' %>
46 <% end %> 46 <% end %>
47 <%= button(:back, _('Back'), :controller => 'profile_editor', :action => 'index') %> 47 <%= button(:back, _('Back'), :controller => 'profile_editor', :action => 'index') %>
48 <% end %> 48 <% end %>
app/views/shared/user_menu.html.erb
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 </li> 20 </li>
21 21
22 <li> 22 <li>
23 - <%= lightbox_link_to('<span class="icon-new"></span>' + _('New article'), '/myprofile/{login}/cms/new') %> 23 + <%= modal_link_to '<span class="icon-new"></span>' + _('New article'), '/myprofile/{login}/cms/new' %>
24 </li> 24 </li>
25 25
26 <li id='manage-enterprises-link-template' style='display: none'><a href='/myprofile/{identifier}'><span class="icon-menu-enterprise"></span><%= _('Manage %s') % '{name}' %></a></li> 26 <li id='manage-enterprises-link-template' style='display: none'><a href='/myprofile/{identifier}'><span class="icon-menu-enterprise"></span><%= _('Manage %s') % '{name}' %></a></li>
@@ -58,9 +58,9 @@ @@ -58,9 +58,9 @@
58 <% if theme_option( :menu_login ) == 'full_form' %> 58 <% if theme_option( :menu_login ) == 'full_form' %>
59 <%= render :file => 'account/login_block' %> 59 <%= render :file => 'account/login_block' %>
60 <% else %> 60 <% else %>
61 - <%= thickbox_inline_popup_link('<span class="icon-menu-login"></span>'+ _('Login'), login_url, 'inlineLoginBox', :id => 'link_login') %> 61 + <%= modal_inline_link_to('<span class="icon-menu-login"></span>'+ _('Login'), login_url, '#inlineLoginBox', :id => 'link_login') %>
62 <div id='inlineLoginBox' style='display: none;'> 62 <div id='inlineLoginBox' style='display: none;'>
63 - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> 63 + <%= render :file => 'account/login', :locals => { :is_popin => true } %>
64 </div> 64 </div>
65 <% end %> 65 <% end %>
66 <% end %> 66 <% end %>
config/database.yml.multitenancy
1 # Refer to INSTALL.multitenancy for more information on Multitenancy support 1 # Refer to INSTALL.multitenancy for more information on Multitenancy support
2 -env1_production: 2 +env1_production: &DEFAULT
3 adapter: postgresql 3 adapter: postgresql
4 encoding: unicode 4 encoding: unicode
5 database: noosfero 5 database: noosfero
@@ -30,4 +30,4 @@ env3_production: @@ -30,4 +30,4 @@ env3_production:
30 - env3.net 30 - env3.net
31 31
32 production: 32 production:
33 - env1_production 33 + <<: *DEFAULT
config/noosfero.yml.dist
@@ -9,6 +9,7 @@ development: @@ -9,6 +9,7 @@ development:
9 googlemaps_initial_zoom: 4 9 googlemaps_initial_zoom: 4
10 exception_recipients: [admin@example.com] 10 exception_recipients: [admin@example.com]
11 max_upload_size: 5MB 11 max_upload_size: 5MB
  12 + hours_until_user_activation_check: 72
12 13
13 test: 14 test:
14 15
config/schedule.rb
@@ -25,6 +25,6 @@ every 1.day do @@ -25,6 +25,6 @@ every 1.day do
25 runner "SearchTerm.calculate_scores" 25 runner "SearchTerm.calculate_scores"
26 end 26 end
27 27
28 -every 90.days do 28 +every 30.days do
29 runner "ProfileSuggestion.generate_all_profile_suggestions" 29 runner "ProfileSuggestion.generate_all_profile_suggestions"
30 end 30 end
db/migrate/20140519113821_add_last_login_at_to_user.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddLastLoginAtToUser < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :users, :last_login_at, :datetime
  4 + end
  5 +
  6 + def self.down
  7 + remove_column :users, :last_login_at
  8 + end
  9 +end
db/migrate/20150112233715_normalize_users_email.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class NormalizeUsersEmail < ActiveRecord::Migration
  2 + def up
  3 + User.find_each do |u|
  4 + u.update_column :email, u.send(:normalize_email)
  5 + end
  6 + end
  7 +
  8 + def down
  9 + say "this migration can't be reverted"
  10 + end
  11 +end
@@ -733,6 +733,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -733,6 +733,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
733 t.string "activation_code", :limit => 40 733 t.string "activation_code", :limit => 40
734 t.datetime "activated_at" 734 t.datetime "activated_at"
735 t.string "return_to" 735 t.string "return_to"
  736 + t.datetime "last_login_at"
736 end 737 end
737 738
738 create_table "validation_infos", :force => true do |t| 739 create_table "validation_infos", :force => true do |t|
debian/control
@@ -48,7 +48,6 @@ Depends: adduser, @@ -48,7 +48,6 @@ Depends: adduser,
48 ruby-feedparser, 48 ruby-feedparser,
49 ruby-feedparser (>= 0.7-3~), 49 ruby-feedparser (>= 0.7-3~),
50 ruby-gettext, 50 ruby-gettext,
51 - ruby-hpricot,  
52 ruby-memcache-client, 51 ruby-memcache-client,
53 ruby-minitest, 52 ruby-minitest,
54 ruby-nokogiri, 53 ruby-nokogiri,
lib/authenticated_system.rb
@@ -5,22 +5,23 @@ module AuthenticatedSystem @@ -5,22 +5,23 @@ module AuthenticatedSystem
5 def logged_in? 5 def logged_in?
6 current_user != nil 6 current_user != nil
7 end 7 end
8 - 8 +
9 # Accesses the current user from the session. 9 # Accesses the current user from the session.
10 def current_user 10 def current_user
11 @current_user ||= (session[:user] && User.find_by_id(session[:user])) || nil 11 @current_user ||= (session[:user] && User.find_by_id(session[:user])) || nil
12 end 12 end
13 - 13 +
14 # Store the given user in the session. 14 # Store the given user in the session.
15 def current_user=(new_user) 15 def current_user=(new_user)
16 if new_user.nil? 16 if new_user.nil?
17 session.delete(:user) 17 session.delete(:user)
18 else 18 else
19 session[:user] = new_user.id 19 session[:user] = new_user.id
  20 + new_user.register_login
20 end 21 end
21 @current_user = new_user 22 @current_user = new_user
22 end 23 end
23 - 24 +
24 # Check if the user is authorized. 25 # Check if the user is authorized.
25 # 26 #
26 # Override this method in your controllers if you want to restrict access 27 # Override this method in your controllers if you want to restrict access
@@ -62,7 +63,7 @@ module AuthenticatedSystem @@ -62,7 +63,7 @@ module AuthenticatedSystem
62 access_denied 63 access_denied
63 end 64 end
64 end 65 end
65 - 66 +
66 # Redirect as appropriate when an access request fails. 67 # Redirect as appropriate when an access request fails.
67 # 68 #
68 # The default action is to redirect to the login screen. 69 # The default action is to redirect to the login screen.
@@ -88,15 +89,15 @@ module AuthenticatedSystem @@ -88,15 +89,15 @@ module AuthenticatedSystem
88 end 89 end
89 end 90 end
90 false 91 false
91 - end  
92 - 92 + end
  93 +
93 # Store the URI of the current request in the session. 94 # Store the URI of the current request in the session.
94 # 95 #
95 # We can return to this location by calling #redirect_back_or_default. 96 # We can return to this location by calling #redirect_back_or_default.
96 def store_location(location = request.url) 97 def store_location(location = request.url)
97 session[:return_to] = location 98 session[:return_to] = location
98 end 99 end
99 - 100 +
100 # Redirect to the URI stored by the most recent store_location call or 101 # Redirect to the URI stored by the most recent store_location call or
101 # to the passed default. 102 # to the passed default.
102 def redirect_back_or_default(default) 103 def redirect_back_or_default(default)
@@ -106,7 +107,7 @@ module AuthenticatedSystem @@ -106,7 +107,7 @@ module AuthenticatedSystem
106 redirect_to(default) 107 redirect_to(default)
107 end 108 end
108 end 109 end
109 - 110 +
110 # Inclusion hook to make #current_user and #logged_in? 111 # Inclusion hook to make #current_user and #logged_in?
111 # available as ActionView helper methods. 112 # available as ActionView helper methods.
112 def self.included(base) 113 def self.included(base)
@@ -132,6 +133,6 @@ module AuthenticatedSystem @@ -132,6 +133,6 @@ module AuthenticatedSystem
132 def get_auth_data 133 def get_auth_data
133 auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) } 134 auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
134 auth_data = request.env[auth_key].to_s.split unless auth_key.blank? 135 auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
135 - return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] 136 + return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
136 end 137 end
137 end 138 end
lib/noosfero/plugin.rb
@@ -24,11 +24,17 @@ class Noosfero::Plugin @@ -24,11 +24,17 @@ class Noosfero::Plugin
24 24
25 def initialize! 25 def initialize!
26 return if !should_load 26 return if !should_load
27 - available_plugins.each do |plugin_dir| 27 +
  28 + klasses = available_plugins.map do |plugin_dir|
28 plugin_name = File.basename(plugin_dir) 29 plugin_name = File.basename(plugin_dir)
29 - plugin = load_plugin(plugin_name)  
30 - load_plugin_extensions(plugin_dir)  
31 - load_plugin_filters(plugin) 30 + load_plugin plugin_name
  31 + end
  32 + available_plugins.each do |plugin_dir|
  33 + load_plugin_extensions plugin_dir
  34 + end
  35 + # filters must be loaded after all extensions
  36 + klasses.each do |plugin|
  37 + load_plugin_filters plugin
32 end 38 end
33 end 39 end
34 40
@@ -88,7 +94,7 @@ class Noosfero::Plugin @@ -88,7 +94,7 @@ class Noosfero::Plugin
88 # This is a generic method that initialize any possible filter defined by a 94 # This is a generic method that initialize any possible filter defined by a
89 # plugin to a specific controller 95 # plugin to a specific controller
90 def load_plugin_filters(plugin) 96 def load_plugin_filters(plugin)
91 - Rails.configuration.to_prepare do 97 + ActionDispatch::Reloader.to_prepare do
92 filters = plugin.new.send 'application_controller_filters' rescue [] 98 filters = plugin.new.send 'application_controller_filters' rescue []
93 Noosfero::Plugin.add_controller_filters ApplicationController, plugin, filters 99 Noosfero::Plugin.add_controller_filters ApplicationController, plugin, filters
94 100
@@ -116,7 +122,7 @@ class Noosfero::Plugin @@ -116,7 +122,7 @@ class Noosfero::Plugin
116 end 122 end
117 123
118 def load_plugin_extensions(dir) 124 def load_plugin_extensions(dir)
119 - Rails.configuration.to_prepare do 125 + ActionDispatch::Reloader.to_prepare do
120 Dir[File.join(dir, 'lib', 'ext', '*.rb')].each {|file| require_dependency file } 126 Dir[File.join(dir, 'lib', 'ext', '*.rb')].each {|file| require_dependency file }
121 end 127 end
122 end 128 end
lib/noosfero/plugin/macro.rb
@@ -35,7 +35,7 @@ class Noosfero::Plugin::Macro @@ -35,7 +35,7 @@ class Noosfero::Plugin::Macro
35 def attributes(macro) 35 def attributes(macro)
36 macro.attributes.to_hash. 36 macro.attributes.to_hash.
37 select {|key, value| key[0..10] == 'data-macro-'}. 37 select {|key, value| key[0..10] == 'data-macro-'}.
38 - inject({}){|result, a| result.merge({a[0][11..-1] => a[1]})}. 38 + inject({}){|result, a| result.merge({a[0][11..-1] => a[1].to_s})}.
39 with_indifferent_access 39 with_indifferent_access
40 end 40 end
41 41
lib/noosfero/plugin/routes.rb
1 plugins_root = Rails.env.test? ? 'plugins' : '{baseplugins,config/plugins}' 1 plugins_root = Rails.env.test? ? 'plugins' : '{baseplugins,config/plugins}'
  2 +prefixes_by_folder = {public: 'plugin',
  3 + profile: 'profile/:profile/plugin',
  4 + myprofile: 'myprofile/:profile/plugin',
  5 + admin: 'admin/plugin'}
2 6
3 Dir.glob(Rails.root.join(plugins_root, '*', 'controllers')) do |controllers_dir| 7 Dir.glob(Rails.root.join(plugins_root, '*', 'controllers')) do |controllers_dir|
4 - prefixes_by_folder = {'public' => 'plugin',  
5 - 'profile' => 'profile/:profile/plugin',  
6 - 'myprofile' => 'myprofile/:profile/plugin',  
7 - 'admin' => 'admin/plugin'} 8 + plugin_name = File.basename(File.dirname(controllers_dir))
8 9
9 controllers_by_folder = prefixes_by_folder.keys.inject({}) do |hash, folder| 10 controllers_by_folder = prefixes_by_folder.keys.inject({}) do |hash, folder|
10 - hash.merge!({folder => Dir.glob(File.join(controllers_dir, folder, '*')).map {|full_names| File.basename(full_names).gsub(/_controller.rb$/,'')}}) 11 + path = "#{controllers_dir}/#{folder}/"
  12 + hash[folder] = Dir.glob("#{path}{*.rb,#{plugin_name}_plugin/*.rb}").map do |filename|
  13 + filename.gsub(path, '').gsub(/_controller.rb$/, '')
  14 + end
  15 + hash
11 end 16 end
12 17
13 - plugin_name = File.basename(File.dirname(controllers_dir))  
14 -  
15 controllers_by_folder.each do |folder, controllers| 18 controllers_by_folder.each do |folder, controllers|
16 controllers.each do |controller| 19 controllers.each do |controller|
17 controller_name = controller.gsub("#{plugin_name}_plugin_",'') 20 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
lib/noosfero/plugin/spammable.rb
1 -Rails.configuration.to_prepare do 1 +ActionDispatch::Reloader.to_prepare do
2 Spammable.module_eval do 2 Spammable.module_eval do
3 def marked_as_spam 3 def marked_as_spam
4 plugins.dispatch(:marked_as_spam, self) 4 plugins.dispatch(:marked_as_spam, self)
lib/tasks/multitenancy.rake
1 namespace :multitenancy do 1 namespace :multitenancy do
2 2
3 - task :create do 3 + task :create => :environment do
4 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) } 4 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) }
5 cd Rails.root.join('config', 'environments'), :verbose => true 5 cd Rails.root.join('config', 'environments'), :verbose => true
6 - file_envs = Dir.glob "{*_development.rb,*_prodution.rb,*_test.rb}" 6 + file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env } 7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env }
8 end 8 end
9 9
10 - task :remove do 10 + task :remove => :environment do
11 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) } 11 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) }
12 cd Rails.root.join('config', 'environments'), :verbose => true 12 cd Rails.root.join('config', 'environments'), :verbose => true
13 - file_envs = Dir.glob "{*_development.rb,*_prodution.rb,*_test.rb}" 13 + file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env } 14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env }
15 end 15 end
16 16
lib/tasks/plugins_tests.rake
@@ -106,7 +106,7 @@ def run_test(name, files) @@ -106,7 +106,7 @@ def run_test(name, files)
106 files = Array(files) 106 files = Array(files)
107 plugin = filename2plugin(files.first) 107 plugin = filename2plugin(files.first)
108 if name == :cucumber || name == :selenium 108 if name == :cucumber || name == :selenium
109 - run_cucumber task2_profile(name, plugin), files 109 + run_cucumber task2profile(name, plugin), files
110 else 110 else
111 run_testrb files 111 run_testrb files
112 end 112 end
@@ -134,7 +134,11 @@ end @@ -134,7 +134,11 @@ end
134 134
135 def run_tests(name, plugins, run=:all) 135 def run_tests(name, plugins, run=:all)
136 plugins = Array(plugins) 136 plugins = Array(plugins)
137 - glob = "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}" 137 + if name == :cucumber || name == :selenium
  138 + glob = "plugins/{#{plugins.join(',')}}/#{task2folder(name)}/**/*.#{task2ext(name)}"
  139 + else
  140 + glob = "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}"
  141 + end
138 files = Dir.glob(glob) 142 files = Dir.glob(glob)
139 if files.empty? 143 if files.empty?
140 puts "I: no tests to run #{name}" 144 puts "I: no tests to run #{name}"
plugins/bsc/public/jquery.ui.spinner
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -Subproject commit bd879003043b4a93b78cbd4a582b6e0650900bcb  
plugins/comment_classification/features/step_definitions/plugin_steps.rb
1 Given /^CommentClassificationPlugin is enabled$/ do 1 Given /^CommentClassificationPlugin is enabled$/ do
2 - step %{I am logged in as admin}  
3 - step %{I am on the environment control panel}  
4 - step %{I follow "Plugins"}  
5 - step %{I check "Comment Classification"}  
6 - step %{I press "Save changes"} 2 + steps %Q{
  3 + Given I am logged in as admin
  4 + Given I am on the environment control panel
  5 + Given I follow "Plugins"
  6 + Given I check "Comment Classification"
  7 + Given I press "Save changes"
  8 + }
  9 +
7 Environment.default.enabled_plugins.should include("CommentClassificationPlugin") 10 Environment.default.enabled_plugins.should include("CommentClassificationPlugin")
8 end 11 end
9 12
plugins/comment_classification/lib/ext/comment.rb
1 require_dependency 'comment' 1 require_dependency 'comment'
2 -require 'comment_classification_plugin.rb'  
3 -require 'comment_classification_plugin/label.rb'  
4 2
5 class Comment 3 class Comment
6 4
plugins/comment_group/lib/ext/article.rb
@@ -9,7 +9,7 @@ class Article @@ -9,7 +9,7 @@ class Article
9 def not_empty_group_comments_removed 9 def not_empty_group_comments_removed
10 if body && body_changed? 10 if body && body_changed?
11 groups_with_comments = Comment.find(:all, :select => 'distinct group_id', :conditions => {:source_id => self.id}).map(&:group_id).compact 11 groups_with_comments = Comment.find(:all, :select => 'distinct group_id', :conditions => {:source_id => self.id}).map(&:group_id).compact
12 - groups = Hpricot(body.to_s).search('.macro').collect{|element| element['data-macro-group_id'].to_i} 12 + groups = Nokogiri::HTML.fragment(body.to_s).css('.macro').collect{|element| element['data-macro-group_id'].to_i}
13 errors[:base] << (N_('Not empty group comment cannot be removed')) unless (groups_with_comments-groups).empty? 13 errors[:base] << (N_('Not empty group comment cannot be removed')) unless (groups_with_comments-groups).empty?
14 end 14 end
15 end 15 end
plugins/community_track/lib/community_track_plugin/track.rb
@@ -59,7 +59,7 @@ class CommunityTrackPlugin::Track &lt; Folder @@ -59,7 +59,7 @@ class CommunityTrackPlugin::Track &lt; Folder
59 59
60 def first_paragraph 60 def first_paragraph
61 return '' if body.blank? 61 return '' if body.blank?
62 - paragraphs = Hpricot(body).search('p') 62 + paragraphs = Nokogiri::HTML.fragment(body).css('p')
63 paragraphs.empty? ? '' : paragraphs.first.to_html 63 paragraphs.empty? ? '' : paragraphs.first.to_html
64 end 64 end
65 65
plugins/custom_forms/public/style.css
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 .edit-information { 25 .edit-information {
26 display: none; 26 display: none;
27 } 27 }
28 -#colorbox .edit-information { 28 +.modal .edit-information {
29 display: block; 29 display: block;
30 } 30 }
31 31
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_select.html.erb
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 <%= labelled_radio_button 'Multiple Select', "fields[#{counter}][kind]", 'multiple_select', field.multiple && field.list %><br /> 26 <%= labelled_radio_button 'Multiple Select', "fields[#{counter}][kind]", 'multiple_select', field.multiple && field.list %><br />
27 27
28 <% button_bar do %> 28 <% button_bar do %>
29 - <%= button :ok, c_('Ok'), '#', :class => 'colorbox-ok-button', :div_id => elem_id %> 29 + <%= button :ok, _('Ok'), '#', :div_id => elem_id %>
30 <% end %> 30 <% end %>
31 </div> 31 </div>
32 32
plugins/oauth_client/Gemfile 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +gem 'omniauth', '~> 1.2.2'
  2 +gem 'omniauth-facebook', '~> 2.0.0'
  3 +gem "omniauth-google-oauth2", '~> 0.2.6'
plugins/oauth_client/README.md 0 → 100644
@@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
  1 +README - Oauth Client Plugin
  2 +================================
  3 +
  4 +OauthClient is a plugin which allow users to login/signup to noosfero with some oauth providers (for now, google, facebook and noosfero itself).
  5 +
  6 +Install
  7 +=======
  8 +
  9 +Enable Plugin
  10 +-------------
  11 +
  12 +cd <your_noosfero_dir>
  13 +./script/noosfero-plugins enable oauth_client
  14 +
  15 +Active Plugin
  16 +-------------
  17 +
  18 +As a Noosfero administrator user, go to administrator panel:
  19 +
  20 +- Click on "Enable/disable plugins" option
  21 +- Click on "Oauth Client Plugin" check-box
  22 +
  23 +Provider Settings
  24 +=================
  25 +
  26 +Goggle
  27 +------
  28 +
  29 +[Create Google+ application](https://developers.google.com/+/web/signin/javascript-flow)
  30 +
  31 +Facebook
  32 +--------
  33 +
  34 +[Create Facebook application](https://developers.facebook.com/docs/facebook-login/v2.1)
  35 +
  36 +Varnish Settings
  37 +================
  38 +If varnish has been used in your stack, you've to bypass the cache for signup page and prevent cookies to be removed when calling the oauth_client plugin callback. E.g.:
  39 +
  40 +```
  41 +if (req.url !~ "^/account/*" && req.url !~ "^/plugin/oauth_provider/*" && req.url !~ "^/plugin/oauth_client/*" && req.http.cookie !~ "_noosfero_.*") {
  42 + unset req.http.cookie;
  43 + return(lookup);
  44 +}
  45 +```
  46 +
  47 +Using Oauth Provider Plugin
  48 +===========================
  49 +The oauth_provider plugin may be used as a provider in the same noosfero installation that hosts your oauth_client plugin (this is usefull in a multi environment setup).
  50 +
  51 +However, you've to use a distinct set of thin processes to handle the authorization requests (to avoid deadlock).
  52 +
  53 +Apache settings example:
  54 +```
  55 +RewriteRule ^/oauth_provider/oauth/(authorize|token).*$ balancer://noosfero-oauth-provider%{REQUEST_URI} [P,QSA,L]
  56 +```
  57 +
  58 +
  59 +Development
  60 +===========
  61 +
  62 +Running OauthClient tests
  63 +--------------------
  64 +
  65 +$ rake test:noosfero_plugins:oauth_client
  66 +
  67 +License
  68 +=======
  69 +
  70 +Copyright (c) The Author developers.
  71 +
  72 +See Noosfero license.
plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +class OauthClientPluginAdminController < AdminController
  2 +
  3 + def index
  4 + end
  5 +
  6 + def new
  7 + @provider = environment.oauth_providers.new
  8 + render :file => 'oauth_client_plugin_admin/edit'
  9 + end
  10 +
  11 + def remove
  12 + environment.oauth_providers.find(params[:id]).destroy
  13 + redirect_to :action => 'index'
  14 + end
  15 +
  16 + def edit
  17 + @provider = params[:id] ? environment.oauth_providers.find(params[:id]) : environment.oauth_providers.new
  18 + if request.post?
  19 + if @provider.update_attributes(params['oauth_client_plugin_provider'])
  20 + session[:notice] = _('Saved!')
  21 + else
  22 + session[:notice] = _('Error!')
  23 + end
  24 + end
  25 + end
  26 +
  27 +end
plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +class OauthClientPluginPublicController < PublicController
  2 +
  3 + skip_before_filter :login_required
  4 +
  5 + def callback
  6 + auth = request.env["omniauth.auth"]
  7 + user = environment.users.find_by_email(auth.info.email)
  8 + user ? login(user) : signup(auth)
  9 + end
  10 +
  11 + def failure
  12 + session[:notice] = _('Failed to login')
  13 + redirect_to root_url
  14 + end
  15 +
  16 + def destroy
  17 + session[:user] = nil
  18 + redirect_to root_url
  19 + end
  20 +
  21 + protected
  22 +
  23 + def login(user)
  24 + provider = OauthClientPlugin::Provider.find(session[:provider_id])
  25 + user_provider = user.oauth_user_providers.find_by_provider_id(provider.id)
  26 + unless user_provider
  27 + user_provider = user.oauth_user_providers.create(:user => user, :provider => provider, :enabled => true)
  28 + end
  29 + if user_provider.enabled? && provider.enabled?
  30 + session[:user] = user.id
  31 + else
  32 + session[:notice] = _("Can't login with #{provider.name}")
  33 + end
  34 +
  35 + redirect_to :controller => :account, :action => :login
  36 + end
  37 +
  38 + def signup(auth)
  39 + login = auth.info.email.split('@').first
  40 + session[:oauth_data] = auth
  41 + name = auth.info.name
  42 + name ||= auth.extra && auth.extra.raw_info ? auth.extra.raw_info.name : ''
  43 + redirect_to :controller => :account, :action => :signup, :user => {:login => login, :email => auth.info.email}, :profile_data => {:name => name}
  44 + end
  45 +
  46 +end
plugins/oauth_client/db/migrate/20141010135314_create_oauth_client_plugin_provider.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class CreateOauthClientPluginProvider < ActiveRecord::Migration
  2 +
  3 + def self.up
  4 + create_table :oauth_client_plugin_providers do |t|
  5 + t.integer :environment_id
  6 + t.string :strategy
  7 + t.string :name
  8 + t.text :options
  9 + t.boolean :enabled
  10 + t.integer :image_id
  11 +
  12 + t.timestamps
  13 + end
  14 + end
  15 +
  16 + def self.down
  17 + drop_table :oauth_client_plugin_providers
  18 + end
  19 +end
plugins/oauth_client/db/migrate/20141014162710_create_oauth_client_user_providers.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class CreateOauthClientUserProviders < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :oauth_client_plugin_user_providers do |t|
  4 + t.references :user
  5 + t.references :provider
  6 + t.boolean :enabled
  7 + t.timestamps
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + drop_table :oauth_client_plugin_user_providers
  13 + end
  14 +end
plugins/oauth_client/lib/ext/environment.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +require_dependency 'environment'
  2 +
  3 +class Environment
  4 +
  5 + has_many :oauth_providers, :class_name => 'OauthClientPlugin::Provider'
  6 +
  7 +end
plugins/oauth_client/lib/ext/user.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +require_dependency 'user'
  2 +
  3 +class User
  4 +
  5 + has_many :oauth_user_providers, :class_name => 'OauthClientPlugin::UserProvider'
  6 + has_many :oauth_providers, :through => :oauth_user_providers, :source => :provider
  7 +
  8 + def password_required_with_oauth?
  9 + password_required_without_oauth? && oauth_providers.empty?
  10 + end
  11 +
  12 + alias_method_chain :password_required?, :oauth
  13 +
  14 + after_create :activate_oauth_user
  15 +
  16 + def activate_oauth_user
  17 + unless oauth_providers.empty?
  18 + activate
  19 + oauth_providers.each do |provider|
  20 + OauthClientPlugin::UserProvider.create!(:user => self, :provider => provider, :enabled => true)
  21 + end
  22 + end
  23 + end
  24 +
  25 + def make_activation_code_with_oauth
  26 + oauth_providers.blank? ? make_activation_code_without_oauth : nil
  27 + end
  28 +
  29 + alias_method_chain :make_activation_code, :oauth
  30 +
  31 +end
plugins/oauth_client/lib/oauth_client_plugin.rb 0 → 100644
@@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
  1 +require 'omniauth/strategies/noosfero_oauth2'
  2 +
  3 +class OauthClientPlugin < Noosfero::Plugin
  4 +
  5 + def self.plugin_name
  6 + "Oauth Client Plugin"
  7 + end
  8 +
  9 + def self.plugin_description
  10 + _("Login with Oauth.")
  11 + end
  12 +
  13 + def login_extra_contents
  14 + plugin = self
  15 + proc do
  16 + render :partial => 'auth/oauth_login', :locals => {:providers => environment.oauth_providers.enabled}
  17 + end
  18 + end
  19 +
  20 + def signup_extra_contents
  21 + plugin = self
  22 +
  23 + proc do
  24 + if plugin.context.session[:oauth_data].present?
  25 + render :partial => 'account/oauth_signup'
  26 + else
  27 + ''
  28 + end
  29 + end
  30 + end
  31 +
  32 + PROVIDERS = {
  33 + :facebook => {
  34 + :name => 'Facebook'
  35 + },
  36 + :google_oauth2 => {
  37 + :name => 'Google'
  38 + },
  39 + :noosfero_oauth2 => {
  40 + :name => 'Noosfero'
  41 + }
  42 + }
  43 +
  44 + def stylesheet?
  45 + true
  46 + end
  47 +
  48 + OmniAuth.config.on_failure = OauthClientPluginPublicController.action(:failure)
  49 +
  50 + Rails.application.config.middleware.use OmniAuth::Builder do
  51 + PROVIDERS.each do |provider, options|
  52 + setup = lambda { |env|
  53 + request = Rack::Request.new(env)
  54 + strategy = env['omniauth.strategy']
  55 +
  56 + Noosfero::MultiTenancy.setup!(request.host)
  57 + domain = Domain.find_by_name(request.host)
  58 + environment = domain.environment rescue Environment.default
  59 +
  60 + provider_id = request.params['id']
  61 + provider_id ||= request.session['omniauth.params']['id'] if request.session['omniauth.params']
  62 + provider = environment.oauth_providers.find(provider_id)
  63 + strategy.options.merge!(provider.options.symbolize_keys)
  64 +
  65 + request.session[:provider_id] = provider_id
  66 + }
  67 +
  68 + provider provider, :setup => setup,
  69 + :path_prefix => '/plugin/oauth_client',
  70 + :callback_path => "/plugin/oauth_client/public/callback/#{provider}",
  71 + :client_options => { :connection_opts => { :proxy => ENV["OAUTH_HTTP_PROXY"] } }
  72 + end
  73 +
  74 + unless Rails.env.production?
  75 + provider :developer, :path_prefix => "/plugin/oauth_client", :callback_path => "/plugin/oauth_client/public/callback/developer"
  76 + end
  77 + end
  78 +
  79 + def account_controller_filters
  80 + {
  81 + :type => 'before_filter', :method_name => 'signup',
  82 + :block => proc {
  83 + auth = session[:oauth_data]
  84 +
  85 + if auth.present? && params[:user].present?
  86 + params[:user][:oauth_providers] = [OauthClientPlugin::Provider.find(session[:provider_id])]
  87 + if request.post? && auth.info.email != params[:user][:email]
  88 + raise "Wrong email for oauth signup"
  89 + end
  90 + end
  91 + }
  92 + }
  93 + end
  94 +
  95 +end
plugins/oauth_client/lib/oauth_client_plugin/provider.rb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +class OauthClientPlugin::Provider < Noosfero::Plugin::ActiveRecord
  2 +
  3 + belongs_to :environment
  4 +
  5 + validates_presence_of :name, :strategy
  6 +
  7 + acts_as_having_image
  8 + acts_as_having_settings :field => :options
  9 +
  10 + settings_items :client_id, :type => :string
  11 + settings_items :client_secret, :type => :string
  12 + settings_items :client_options, :type => Hash
  13 +
  14 + attr_accessible :name, :environment, :strategy, :client_id, :client_secret, :enabled, :client_options, :image_builder
  15 +
  16 + scope :enabled, :conditions => {:enabled => true}
  17 +
  18 + acts_as_having_image
  19 +
  20 +end
plugins/oauth_client/lib/oauth_client_plugin/user_provider.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class OauthClientPlugin::UserProvider < Noosfero::Plugin::ActiveRecord
  2 +
  3 + belongs_to :user, :class_name => 'User'
  4 + belongs_to :provider, :class_name => 'OauthClientPlugin::Provider'
  5 +
  6 + set_table_name :oauth_client_plugin_user_providers
  7 +
  8 + attr_accessible :user, :provider, :enabled
  9 +
  10 +end
plugins/oauth_client/lib/omniauth/strategies/noosfero_oauth2.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +require 'omniauth/strategies/oauth2'
  2 +
  3 +module OmniAuth
  4 + module Strategies
  5 + class NoosferoOauth2 < OmniAuth::Strategies::OAuth2
  6 + option :name, :noosfero_oauth2
  7 + option :client_options, {
  8 + :authorize_url => '/oauth_provider/oauth/authorize',
  9 + :token_url => '/oauth_provider/oauth/token'
  10 + }
  11 +
  12 + uid { raw_info["id"] }
  13 +
  14 + info do
  15 + {
  16 + :email => raw_info["email"]
  17 + }
  18 + end
  19 +
  20 + def raw_info
  21 + #FIXME access the noosfero api (coming soon)
  22 + @raw_info ||= access_token.get('/plugin/oauth_provider/public/me').parsed
  23 + end
  24 + end
  25 + end
  26 +end
plugins/oauth_client/public/style.css 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +.oauth-login .provider a {
  2 + min-width: 20px;
  3 + min-height: 20px;
  4 + background-size: 20px;
  5 + display: inline-block;
  6 + text-decoration: none;
  7 + background-repeat: no-repeat;
  8 + line-height: 20px;
  9 +}
  10 +.oauth-login .provider a img {
  11 + max-width: 40px;
  12 +}
  13 +.oauth-login .provider a:hover {
  14 + opacity: 0.7;
  15 +}
  16 +.oauth-login .provider .developer {
  17 + display: none;
  18 +}
plugins/oauth_client/test/functional/oauth_client_plugin_public_controller_test.rb 0 → 100644
@@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class OauthClientPluginPublicControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + @auth = mock
  7 + @auth.stubs(:info).returns(mock)
  8 + request.env["omniauth.auth"] = @auth
  9 + @environment = Environment.default
  10 + @provider = OauthClientPlugin::Provider.create!(:name => 'provider', :strategy => 'provider', :enabled => true)
  11 + end
  12 + attr_reader :auth, :environment, :provider
  13 +
  14 + should 'redirect to signup when user is not found' do
  15 + auth.info.stubs(:email).returns("xyz123@noosfero.org")
  16 + auth.info.stubs(:name).returns('xyz123')
  17 + session[:provider_id] = provider.id
  18 +
  19 + get :callback
  20 + assert_match /.*\/account\/signup/, @response.redirect_url
  21 + end
  22 +
  23 + should 'redirect to login when user is found' do
  24 + user = fast_create(User, :environment_id => environment.id)
  25 + auth.info.stubs(:email).returns(user.email)
  26 + auth.info.stubs(:name).returns(user.name)
  27 + session[:provider_id] = provider.id
  28 +
  29 + get :callback
  30 + assert_redirected_to :controller => :account, :action => :login
  31 + assert_equal user.id, session[:user]
  32 + end
  33 +
  34 + should 'do not login when the provider is disabled' do
  35 + user = fast_create(User, :environment_id => environment.id)
  36 + auth.info.stubs(:email).returns(user.email)
  37 + auth.info.stubs(:name).returns(user.name)
  38 + session[:provider_id] = provider.id
  39 + provider.update_attribute(:enabled, false)
  40 +
  41 + get :callback
  42 + assert_redirected_to :controller => :account, :action => :login
  43 + assert_equal nil, session[:user]
  44 + end
  45 +
  46 + should 'do not login when the provider is disabled for a user' do
  47 + user = fast_create(User, :environment_id => environment.id)
  48 + auth.info.stubs(:email).returns(user.email)
  49 + auth.info.stubs(:name).returns(user.name)
  50 + session[:provider_id] = provider.id
  51 + user.oauth_user_providers.create(:user => user, :provider => provider, :enabled => false)
  52 +
  53 + get :callback
  54 + assert_redirected_to :controller => :account, :action => :login
  55 + assert_equal nil, session[:user]
  56 + end
  57 +
  58 + should 'save provider when an user login with it' do
  59 + user = fast_create(User, :environment_id => environment.id)
  60 + auth.info.stubs(:email).returns(user.email)
  61 + auth.info.stubs(:name).returns(user.name)
  62 + session[:provider_id] = provider.id
  63 +
  64 + get :callback
  65 + assert_equal [provider], user.oauth_providers
  66 + end
  67 +
  68 + should 'do not duplicate relations between an user and a provider when the same provider was used again in a login' do
  69 + user = fast_create(User, :environment_id => environment.id)
  70 + auth.info.stubs(:email).returns(user.email)
  71 + auth.info.stubs(:name).returns(user.name)
  72 + session[:provider_id] = provider.id
  73 +
  74 + get :callback
  75 + assert_no_difference 'user.oauth_user_providers.count' do
  76 + 3.times { get :callback }
  77 + end
  78 + end
  79 +
  80 +end
plugins/oauth_client/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/oauth_client/test/unit/environment_test.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class UserTest < ActiveSupport::TestCase
  4 +
  5 + should 'be able to add oauth providers in a environment' do
  6 + env = fast_create(Environment)
  7 + env.oauth_providers << OauthClientPlugin::Provider.new(:name => 'test', :strategy => 'test')
  8 + end
  9 +
  10 +end
plugins/oauth_client/test/unit/oauth_client_plugin_test.rb 0 → 100644
@@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class OauthClientPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @plugin = OauthClientPlugin.new(self)
  7 + @params = {}
  8 + @plugin.stubs(:context).returns(self)
  9 + @environment = Environment.default
  10 + @session = {}
  11 + @request = mock
  12 + @provider = OauthClientPlugin::Provider.create!(:name => 'name', :strategy => 'strategy')
  13 + end
  14 +
  15 + attr_reader :params, :plugin, :environment, :session, :request, :provider
  16 +
  17 + should 'has extra contents for login' do
  18 + assert plugin.login_extra_contents
  19 + end
  20 +
  21 + should 'has no signup extra contents if no provider was enabled' do
  22 + assert_equal '', instance_eval(&plugin.signup_extra_contents)
  23 + end
  24 +
  25 + should 'has signup extra contents if oauth_data exists in session' do
  26 + session[:oauth_data] = {:oauth => 'test'}
  27 + expects(:render).with(:partial => 'account/oauth_signup').once
  28 + instance_eval(&plugin.signup_extra_contents)
  29 + end
  30 +
  31 + should 'define before filter for account controller' do
  32 + assert plugin.account_controller_filters
  33 + end
  34 +
  35 + should 'raise error if oauth email was changed' do
  36 + request.expects(:post?).returns(true)
  37 +
  38 + oauth_data = mock
  39 + info = mock
  40 + oauth_data.stubs(:info).returns(info)
  41 + oauth_data.stubs(:uid).returns('uid')
  42 + oauth_data.stubs(:provider).returns('provider')
  43 + info.stubs(:email).returns('test@example.com')
  44 + session[:oauth_data] = oauth_data
  45 + session[:provider_id] = provider.id
  46 +
  47 + params[:user] = {:email => 'test2@example.com'}
  48 + assert_raises RuntimeError do
  49 + instance_eval(&plugin.account_controller_filters[:block])
  50 + end
  51 + end
  52 +
  53 + should 'do not raise error if oauth email was not changed' do
  54 + request.expects(:post?).returns(true)
  55 +
  56 + oauth_data = mock
  57 + info = mock
  58 + oauth_data.stubs(:info).returns(info)
  59 + oauth_data.stubs(:uid).returns('uid')
  60 + oauth_data.stubs(:provider).returns('provider')
  61 + info.stubs(:email).returns('test@example.com')
  62 + session[:oauth_data] = oauth_data
  63 + session[:provider_id] = provider.id
  64 +
  65 + params[:user] = {:email => 'test@example.com'}
  66 + instance_eval(&plugin.account_controller_filters[:block])
  67 + end
  68 +
  69 + should 'do not raise error if oauth session is not set' do
  70 + instance_eval(&plugin.account_controller_filters[:block])
  71 + end
  72 +
  73 + should 'do not raise error if it is not a post' do
  74 + request.expects(:post?).returns(false)
  75 + params[:user] = {:email => 'test2@example.com'}
  76 +
  77 + oauth_data = mock
  78 + oauth_data.stubs(:uid).returns('uid')
  79 + oauth_data.stubs(:provider).returns('provider')
  80 + session[:provider_id] = provider.id
  81 +
  82 + session[:oauth_data] = oauth_data
  83 + instance_eval(&plugin.account_controller_filters[:block])
  84 + end
  85 +
  86 +end
plugins/oauth_client/test/unit/user_test.rb 0 → 100644
@@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class UserTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @provider = OauthClientPlugin::Provider.create!(:name => 'name', :strategy => 'strategy')
  7 + end
  8 + attr_reader :provider
  9 +
  10 + should 'password is not required if there is a oauth provider' do
  11 + User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :oauth_providers => [provider])
  12 + end
  13 +
  14 + should 'password is required if there is a oauth provider' do
  15 + user = User.new(:email => 'testoauth@example.com', :login => 'testoauth')
  16 + user.save
  17 + assert user.errors[:password].present?
  18 + end
  19 +
  20 + should 'activate user when created with oauth' do
  21 + user = User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :oauth_providers => [provider])
  22 + assert user.activated?
  23 + end
  24 +
  25 + should 'not activate user when created without oauth' do
  26 + user = fast_create(User)
  27 + assert !user.activated?
  28 + end
  29 +
  30 + should 'not make activation code when created with oauth' do
  31 + user = User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :oauth_providers => [provider])
  32 + assert !user.activation_code
  33 + end
  34 +
  35 + should 'make activation code when created without oauth' do
  36 + user = User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :password => 'test', :password_confirmation => 'test')
  37 + assert user.activation_code
  38 + end
  39 +
  40 +end
plugins/oauth_client/views/account/_oauth_signup.html.erb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<%= hidden_field_tag 'return_to', '/' %>
  2 +
  3 +<style>
  4 + #signup-password, #signup-password-confirmation, #signup-email {
  5 + display: none;
  6 + }
  7 +</style>
  8 +
  9 +<div id='signup-email-readonly'>
  10 + <%= labelled_form_field(_('Email'), text_field(:user, :email, :class => "disabled", :readonly => true)) %>
  11 +</div>
plugins/oauth_client/views/auth/_oauth_login.html.erb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<div class="oauth-login">
  2 + <% unless providers.empty? %>
  3 + <%= _('Login with:') %>
  4 + <% end %>
  5 + <% providers.each do |provider| %>
  6 + <span class="provider">
  7 + <%= link_to provider.image ? image_tag(provider.image.public_filename) : provider.name, "/plugin/oauth_client/#{provider.strategy}?id=#{provider.id}", :class => provider.strategy, :title => provider.name %>
  8 + </span>
  9 + <% end %>
  10 +
  11 + <span class="provider">
  12 + <% unless Rails.env.production? %>
  13 + <%= link_to _('Developer Login'), "/plugin/oauth_client/developer", :class => 'developer' %>
  14 + <% end %>
  15 + </span>
  16 +</div>
plugins/oauth_client/views/oauth_client_plugin_admin/_noosfero_oauth2.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<%= f.fields_for :client_options, OpenStruct.new(provider.options[:client_options]) do |c| %>
  2 + <div class="client-url">
  3 + <%= labelled_form_field _('Client Url'), c.text_field(:site) %>
  4 + </div>
  5 +<% end %>
plugins/oauth_client/views/oauth_client_plugin_admin/edit.html.erb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +<h1><%= _('Oauth Client Settings') %></h1>
  2 +<h3><%= _('Edit Provider') %></h3>
  3 +
  4 +<%= form_for @provider, :url => {:action => 'edit'}, :method => 'post' do |f| %>
  5 +
  6 + <div class="enabled">
  7 + <%= labelled_form_field f.check_box(:enabled) + _('Enabled'), '' %>
  8 + </div>
  9 +
  10 + <div class="name">
  11 + <%= labelled_form_field _('Name'), f.text_field(:name) %>
  12 + </div>
  13 +
  14 + <div class="strategy">
  15 + <%= labelled_form_field _('Strategy'), f.select(:strategy, OauthClientPlugin::PROVIDERS) %>
  16 + </div>
  17 +
  18 + <div class="client-id">
  19 + <%= labelled_form_field _('Client Id'), f.text_field(:client_id) %>
  20 + </div>
  21 +
  22 + <div class="client-secret">
  23 + <%= labelled_form_field _('Client Secret'), f.text_field(:client_secret) %>
  24 + </div>
  25 +
  26 + <% if File.exists?(File.join(File.dirname(__FILE__), "_#{@provider.strategy}.html.erb")) %>
  27 + <%= render :partial => "#{@provider.strategy}", :locals => {:f => f, :provider => @provider} %>
  28 + <% end %>
  29 +
  30 + <div class="image-icon">
  31 + <%= f.fields_for :image_builder, @provider.image do |i| %>
  32 + <%= file_field_or_thumbnail(_('Image:'), @provider.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
  33 + <% end %>
  34 + </div>
  35 +
  36 + <% button_bar do %>
  37 + <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %>
  38 + <% end %>
  39 +<% end %>
plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +<h1><%= _('Oauth Client Settings') %></h1>
  2 +<h3><%= _('Providers') %></h3>
  3 +<%= button :add, _('New'), {:action => 'new'} %>
  4 +<table>
  5 + <tr>
  6 + <th><%= _('Name') %></th>
  7 + <th><%= _('Strategy') %></th>
  8 + <th><%= _('Actions') %></th>
  9 + </tr>
  10 +
  11 + <% environment.oauth_providers.each do |provider| %>
  12 + <tr>
  13 + <td><%= provider.name %></td>
  14 + <td><%= provider.strategy %></td>
  15 + <td>
  16 + <%= link_to _('Edit'), {:action => 'edit', :id => provider.id} %>
  17 + <%= link_to _('Remove'), {:action => 'remove', :id => provider.id} %>
  18 + </td>
  19 + </tr>
  20 + <% end %>
  21 +</table>
  22 +<div class="actions">
  23 + <%= button(:back, _('Go back'), {:controller => 'plugins', :action => 'index'}) %>
  24 +</div>
plugins/oauth_provider/Gemfile 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +gem 'doorkeeper', '~> 1.4.0'
plugins/oauth_provider/README.md 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +README - Oauth Provider Plugin
  2 +================================
  3 +
  4 +OauthProvider is a plugin which allow noosfero to be used as an oauth provider
  5 +
  6 +Install
  7 +=======
  8 +
  9 +Enable Plugin
  10 +-------------
  11 +
  12 +cd <your_noosfero_dir>
  13 +./script/noosfero-plugins enable oauth_provider
  14 +
  15 +Active Plugin
  16 +-------------
  17 +
  18 +As a Noosfero administrator user, go to administrator panel:
  19 +
  20 +- Click on "Enable/disable plugins" option
  21 +- Click on "Oauth Provider Plugin" check-box
  22 +
  23 +Varnish Settings
  24 +================
  25 +If varnish has been used in your stack, you've to prevent cookies to be removed when calling authorization actions for oauth_provider. E.g.:
  26 +
  27 +```
  28 +if (req.url !~ "^/plugin/oauth_provider/*" && req.http.cookie !~ "_noosfero_.*") {
  29 + unset req.http.cookie;
  30 + return(lookup);
  31 +}
  32 +```
  33 +
  34 +Development
  35 +===========
  36 +
  37 +Running OauthProvider tests
  38 +--------------------
  39 +
  40 +$ rake test:noosfero_plugins:oauth_provider
  41 +
  42 +License
  43 +=======
  44 +
  45 +Copyright (c) The Author developers.
  46 +
  47 +See Noosfero license.