Commit b6d2e88c26a5a213eff18d6fd391e750e5acbee8

Authored by Leandro Santos
2 parents d6f4caa4 a6aca8e1

Merge branch 'master' into AI3268_template_management

Showing 298 changed files with 1235 additions and 403 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 298 files displayed.

app/controllers/my_profile/cms_controller.rb
... ... @@ -174,6 +174,8 @@ class CmsController < MyProfileController
174 174  
175 175 post_only :set_home_page
176 176 def set_home_page
  177 + return render_access_denied unless user.can_change_homepage?
  178 +
177 179 article = params[:id].nil? ? nil : profile.articles.find(params[:id])
178 180 profile.update_attribute(:home_page, article)
179 181  
... ... @@ -212,6 +214,7 @@ class CmsController < MyProfileController
212 214 if @errors.any?
213 215 render :action => 'upload_files', :parent_id => @parent_id
214 216 else
  217 + session[:notice] = _('File(s) successfully uploaded')
215 218 if @back_to
216 219 redirect_to @back_to
217 220 elsif @parent
... ...
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController
3 3 needs_profile
4 4  
5 5 protect 'edit_profile_design', :profile
6   -
  6 +
  7 + before_filter :protect_fixed_block, :only => [:save, :move_block]
  8 +
  9 + def protect_fixed_block
  10 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  11 + if block.fixed && !current_person.is_admin?
  12 + render_access_denied
  13 + end
  14 + end
  15 +
7 16 def available_blocks
8 17 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
9 18  
... ...
app/helpers/application_helper.rb
... ... @@ -945,9 +945,9 @@ module ApplicationHelper
945 945 # from Article model for an ArticleBlock.
946 946 def reference_to_article(text, article, anchor=nil)
947 947 if article.profile.domains.empty?
948   - href = "/#{article.url[:profile]}/"
  948 + href = "#{Noosfero.root}/#{article.url[:profile]}/"
949 949 else
950   - href = "http://#{article.profile.domains.first.name}/"
  950 + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
951 951 end
952 952 href += article.url[:page].join('/')
953 953 href += '#' + anchor if anchor
... ...
app/helpers/article_helper.rb
... ... @@ -77,12 +77,59 @@ module ArticleHelper
77 77 content_tag('div',
78 78 radio_button(:article, :published, false) +
79 79 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private")
80   - ) +
81   - (article.profile.community? ? content_tag('div',
82   - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") +
83   - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'},
84   - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) :
85   - ''))
  80 + ) +
  81 + privacity_exceptions(article, tokenized_children)
  82 + )
  83 + end
  84 +
  85 + def privacity_exceptions(article, tokenized_children)
  86 + content_tag('div',
  87 + content_tag('div',
  88 + (
  89 + if article.profile
  90 + add_option_to_followers(article, tokenized_children)
  91 + else
  92 + ''
  93 + end
  94 + )
  95 + ),
  96 + :style => "margin-left:10px"
  97 + )
  98 + end
  99 +
  100 + def add_option_to_followers(article, tokenized_children)
  101 + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends')
  102 +
  103 + check_box(
  104 + :article,
  105 + :show_to_followers,
  106 + {:class => "custom_privacy_option"}
  107 + ) +
  108 + content_tag(
  109 + 'label',
  110 + label_message,
  111 + :for => 'article_show_to_followers',
  112 + :id => 'label_show_to_followers'
  113 + ) +
  114 + (article.profile.community? ?
  115 + content_tag(
  116 + 'div',
  117 + content_tag(
  118 + 'label',
  119 + _('Fill in the search field to add the exception users to see this content'),
  120 + :id => "text-input-search-exception-users"
  121 + ) +
  122 + token_input_field_tag(
  123 + :q,
  124 + 'search-article-privacy-exceptions',
  125 + {:action => 'search_article_privacy_exceptions'},
  126 + {
  127 + :focus => false,
  128 + :hint_text => _('Type in a search term for a user'),
  129 + :pre_populate => tokenized_children
  130 + }
  131 + )
  132 + ) : '')
86 133 end
87 134  
88 135 def prepare_to_token_input(array)
... ...
app/helpers/boxes_helper.rb
... ... @@ -170,49 +170,54 @@ module BoxesHelper
170 170 else
171 171 "before-block-#{block.id}"
172 172 end
173   -
174   - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  173 + if block.nil? or modifiable?(block)
  174 + content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  175 + else
  176 + ""
  177 + end
175 178 end
176 179  
177 180 # makes the given block draggable so it can be moved away.
178 181 def block_handle(block)
179   - draggable_element("block-#{block.id}", :revert => true)
  182 + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
180 183 end
181 184  
182 185 def block_edit_buttons(block)
183 186 buttons = []
184 187 nowhere = 'javascript: return false;'
185 188  
186   - if block.first?
187   - buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
188   - else
189   - buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
190   - end
  189 + if modifiable?(block)
  190 + if block.first?
  191 + buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
  192 + else
  193 + buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
  194 + end
191 195  
192   - if block.last?
193   - buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
194   - else
195   - buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
196   - end
  196 + if block.last?
  197 + buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
  198 + else
  199 + buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
  200 + end
197 201  
198   - holder = block.owner
199   - # move to opposite side
200   - # FIXME too much hardcoded stuff
201   - if holder.layout_template == 'default'
202   - if block.box.position == 2 # area 2, left side => move to right side
203   - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
204   - elsif block.box.position == 3 # area 3, right side => move to left side
205   - buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
  202 + holder = block.owner
  203 + # move to opposite side
  204 + # FIXME too much hardcoded stuff
  205 + if holder.layout_template == 'default'
  206 + if block.box.position == 2 # area 2, left side => move to right side
  207 + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
  208 + elsif block.box.position == 3 # area 3, right side => move to left side
  209 + buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
  210 + end
206 211 end
207   - end
208 212  
209   - if block.editable?
210   - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
211   - end
  213 + if block.editable?
  214 + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  215 + end
212 216  
213   - if !block.main?
214   - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
215   - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
  217 + if !block.main?
  218 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  219 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
  220 + end
216 221 end
217 222  
218 223 if block.respond_to?(:help)
... ... @@ -248,5 +253,7 @@ module BoxesHelper
248 253 classes
249 254 end
250 255  
251   -
  256 + def modifiable?(block)
  257 + return !block.fixed || environment.admins.include?(user)
  258 + end
252 259 end
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -45,7 +45,7 @@ module ContentViewerHelper
45 45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } }
46 46 end
47 47 content_tag(:div, link_to(_('Translations'), '#',
48   - :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false",
  48 + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{CGI::escape_html(links.to_json)}); return false",
49 49 :class => 'article-translations-menu simplemenu-trigger up'),
50 50 :class => 'article-translations')
51 51 end
... ...
app/helpers/layout_helper.rb
... ... @@ -2,6 +2,7 @@ module LayoutHelper
2 2  
3 3 def body_classes
4 4 # Identify the current controller and action for the CSS:
  5 + (logged_in? ? " logged-in" : "") +
5 6 " controller-#{controller.controller_name}" +
6 7 " action-#{controller.controller_name}-#{controller.action_name}" +
7 8 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" +
... ...
app/helpers/search_helper.rb
... ... @@ -21,6 +21,12 @@ module SearchHelper
21 21 'more_comments' => _('More comments')
22 22 }
23 23  
  24 + COMMON_PROFILE_LIST_BLOCK = [
  25 + :enterprises,
  26 + :people,
  27 + :communities
  28 + ]
  29 +
24 30 # FIXME remove it after search_controler refactored
25 31 include EventsHelper
26 32  
... ... @@ -94,7 +100,7 @@ module SearchHelper
94 100 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil
95 101 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil
96 102 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil
97   - content_tag('div',
  103 + content_tag('div',
98 104 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe,
99 105 :class => 'search-customize-options'
100 106 )
... ...
app/models/article.rb
... ... @@ -2,7 +2,14 @@ require &#39;hpricot&#39;
2 2  
3 3 class Article < ActiveRecord::Base
4 4  
5   - attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, :allow_members_to_edit, :translation_of_id, :language, :license_id, :parent_id, :display_posts_in_current_language, :category_ids, :posts_per_page, :moderate_comments, :accept_comments, :feed, :published, :source, :highlighted, :notify_comments, :display_hits, :slug, :external_feed_builder, :display_versions, :external_link, :image_builder
  5 + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent,
  6 + :allow_members_to_edit, :translation_of_id, :language,
  7 + :license_id, :parent_id, :display_posts_in_current_language,
  8 + :category_ids, :posts_per_page, :moderate_comments,
  9 + :accept_comments, :feed, :published, :source,
  10 + :highlighted, :notify_comments, :display_hits, :slug,
  11 + :external_feed_builder, :display_versions, :external_link,
  12 + :image_builder, :show_to_followers
6 13  
7 14 acts_as_having_image
8 15  
... ... @@ -333,7 +340,7 @@ class Article &lt; ActiveRecord::Base
333 340 def belongs_to_blog?
334 341 self.parent and self.parent.blog?
335 342 end
336   -
  343 +
337 344 def belongs_to_forum?
338 345 self.parent and self.parent.forum?
339 346 end
... ... @@ -445,6 +452,7 @@ class Article &lt; ActiveRecord::Base
445 452 if self.parent && !self.parent.published?
446 453 return false
447 454 end
  455 +
448 456 true
449 457 else
450 458 false
... ... @@ -476,14 +484,17 @@ class Article &lt; ActiveRecord::Base
476 484 {:conditions => [" articles.published = ? OR
477 485 articles.last_changed_by_id = ? OR
478 486 articles.profile_id = ? OR
479   - ?",
480   - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] }
  487 + ? OR articles.show_to_followers = ? AND ?",
  488 + true, user.id, user.id, user.has_permission?(:view_private_content, profile),
  489 + true, user.follows?(profile)]}
481 490 end
482 491  
  492 +
483 493 def display_unpublished_article_to?(user)
484 494 user == author || allow_view_private_content?(user) || user == profile ||
485 495 user.is_admin?(profile.environment) || user.is_admin?(profile) ||
486   - article_privacy_exceptions.include?(user)
  496 + article_privacy_exceptions.include?(user) ||
  497 + (self.show_to_followers && user.follows?(profile))
487 498 end
488 499  
489 500 def display_to?(user = nil)
... ...
app/models/block.rb
1 1 class Block < ActiveRecord::Base
2 2  
3   - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box
  3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed
4 4  
5 5 # to be able to generate HTML
6 6 include ActionView::Helpers::UrlHelper
... ... @@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base
64 64 end
65 65  
66 66 def display_to_user?(user)
67   - display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged')
  67 + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner))
68 68 end
69 69  
70 70 def display_always(context)
... ... @@ -110,6 +110,9 @@ class Block &lt; ActiveRecord::Base
110 110 # * <tt>'all'</tt>: the block is always displayed
111 111 settings_items :language, :type => :string, :default => 'all'
112 112  
  113 + # The block can be configured to be fixed. Only can be edited by environment admins
  114 + settings_items :fixed, :type => :boolean, :default => false
  115 +
113 116 # returns the description of the block, used when the user sees a list of
114 117 # blocks to choose one to include in the design.
115 118 #
... ... @@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base
221 224 'all' => _('All users'),
222 225 'logged' => _('Logged'),
223 226 'not_logged' => _('Not logged'),
  227 + 'followers' => owner.organization? ? _('Members') : _('Friends')
224 228 }
225 229 end
226 230  
... ...
app/models/blog.rb
... ... @@ -53,7 +53,7 @@ class Blog &lt; Folder
53 53 def prepare_external_feed
54 54 unless self.external_feed_data.nil?
55 55 if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i
56   - self.external_feed.attributes = self.external_feed_data
  56 + self.external_feed.attributes = self.external_feed_data.except(:id)
57 57 else
58 58 self.build_external_feed(self.external_feed_data, :without_protection => true)
59 59 end
... ...
app/models/environment.rb
... ... @@ -283,6 +283,7 @@ class Environment &lt; ActiveRecord::Base
283 283 www.flickr.com
284 284 www.gmodules.com
285 285 www.youtube.com
  286 + openstreetmap.org
286 287 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"}
287 288  
288 289 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names
... ...
app/models/external_feed.rb
... ... @@ -10,7 +10,7 @@ class ExternalFeed &lt; ActiveRecord::Base
10 10 { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] }
11 11 }
12 12  
13   - attr_accessible :address, :enabled
  13 + attr_accessible :address, :enabled, :only_once
14 14  
15 15 def add_item(title, link, date, content)
16 16 return if content.blank?
... ...
app/models/invitation.rb
... ... @@ -65,18 +65,16 @@ class Invitation &lt; Task
65 65  
66 66 task_args = if user.nil?
67 67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message}
68   - elsif !user.person.is_a_friend?(person)
  68 + else
69 69 {:person => person, :target => user.person}
70 70 end
71 71  
72   - if !task_args.nil?
73   - if profile.person?
74   - InviteFriend.create(task_args)
75   - elsif profile.community?
76   - InviteMember.create(task_args.merge(:community_id => profile.id))
77   - else
78   - raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s
79   - end
  72 + if profile.person?
  73 + InviteFriend.create(task_args) if user.nil? || !user.person.is_a_friend?(person)
  74 + elsif profile.community?
  75 + InviteMember.create(task_args.merge(:community_id => profile.id)) if user.nil? || !user.person.is_member_of?(profile)
  76 + else
  77 + raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s
80 78 end
81 79 end
82 80 end
... ...
app/models/person.rb
... ... @@ -80,6 +80,10 @@ roles] }
80 80  
81 81 belongs_to :user, :dependent => :delete
82 82  
  83 + def can_change_homepage?
  84 + !environment.enabled?('cant_change_homepage') || is_admin?
  85 + end
  86 +
83 87 def can_control_scrap?(scrap)
84 88 begin
85 89 !self.scraps(scrap).nil?
... ...
app/models/product.rb
... ... @@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base
11 11  
12 12 SEARCH_DISPLAYS = %w[map full]
13 13  
14   - attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs
  14 + attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list
15 15  
16 16 def self.default_search_display
17 17 'full'
... ...
app/views/box_organizer/edit.html.erb
... ... @@ -5,6 +5,12 @@
5 5  
6 6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %>
7 7  
  8 + <% if environment.admins.include?(user) %>
  9 + <div class="fixed_block">
  10 + <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %>
  11 + </div>
  12 + <% end %>
  13 +
8 14 <%= render :partial => partial_for_class(@block.class) %>
9 15  
10 16 <div class="display">
... ...
app/views/cms/upload_files.html.erb
... ... @@ -20,5 +20,10 @@
20 20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5>
21 21  
22 22 <%= form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %>
  23 +
  24 + <%= @plugins.dispatch(:upload_files_extra_fields, params[:parent_id]).collect { |content| instance_exec(&content) }.join("") %>
  25 +
23 26 <%= render :partial => 'upload_file_form', :locals => { :size => '45'} %>
24   -<% end %>
  27 +
  28 +<% end %>
  29 +
... ...
app/views/cms/view.html.erb
... ... @@ -2,7 +2,7 @@
2 2 <%= _('Content management') %>
3 3 </h1>
4 4  
5   -<% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %>
  5 +<% if user.can_change_homepage? && !remove_content_button(:home) %>
6 6 <div class="cms-homepage">
7 7 <%= _('Profile homepage:') %>
8 8 <% if profile.home_page %>
... ... @@ -69,7 +69,7 @@
69 69 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %>
70 70 <%= button_without_text :eyes, _('Public view'), article.view_url %>
71 71 <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%>
72   - <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %>
  72 + <% if user.can_change_homepage? && !remove_content_button(:home) %>
73 73 <% if profile.home_page != article %>
74 74 <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
75 75 <% else %>
... ...
app/views/events/events.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <div id='agenda-toolbar'>
4 4 <%= button :back, _('Back to %s') % profile.name, profile.url %>
5 5 <% if user && user.has_permission?('post_content', profile) %>
6   - <%= button :new, _('New event'), myprofile_url(:controller => 'cms', :action => 'new', :type => 'Event') %>
  6 + <%= button :new, _('New event'), myprofile_path(:controller => 'cms', :action => 'new', :type => 'Event') %>
7 7 <% end %>
8 8 </div>
9 9  
... ...
app/views/manage_products/_edit_info.html.erb
... ... @@ -47,7 +47,7 @@
47 47 <%= button_to_function(
48 48 :add,
49 49 _('Add new qualifier'),
50   - "new_qualifier_row('#product-qualifiers-list', '#{escape_javascript(select_qualifiers(@product))}', '#{escape_javascript(remove_qualifier_button)}')"
  50 + "new_qualifier_row('#product-qualifiers-list', '#{escape_javascript(CGI::escape_html(select_qualifiers(@product)))}', '#{escape_javascript(CGI::escape_html(remove_qualifier_button))}')"
51 51 ) %>
52 52 <%= hidden_field_tag "product[qualifiers_list][nil]" %>
53 53 <% end %>
... ...
app/views/search/_display_results.html.erb
... ... @@ -14,7 +14,7 @@
14 14  
15 15 <% display = display_filter(name, params[:display]) %>
16 16  
17   - <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if [:enterprises, :people, :communities].include?(name) %>">
  17 + <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if SearchHelper::COMMON_PROFILE_LIST_BLOCK.include?(name) %>">
18 18 <ul>
19 19 <% search[:results].each do |hit| %>
20 20 <% partial = partial_for_class(hit.class, display) %>
... ...
db/migrate/20150113131617_add_show_to_followers_for_article.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class AddShowToFollowersForArticle < ActiveRecord::Migration
  2 + def up
  3 + add_column :articles, :show_to_followers, :boolean, :default => false
  4 + end
  5 +
  6 + def down
  7 + remove_column :articles, :show_to_followers
  8 + end
  9 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20140827191326) do
  14 +ActiveRecord::Schema.define(:version => 20150113131617) do
15 15  
16 16 create_table "abuse_reports", :force => true do |t|
17 17 t.integer "reporter_id"
... ... @@ -149,6 +149,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do
149 149 t.integer "spam_comments_count", :default => 0
150 150 t.integer "author_id"
151 151 t.integer "created_by_id"
  152 + t.boolean "show_to_followers", :default => false
152 153 end
153 154  
154 155 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
... ...
features/edit_article.feature
... ... @@ -47,6 +47,28 @@ Feature: edit article
47 47 Then I should see "Access denied"
48 48  
49 49 @selenium
  50 + Scenario: Hide token field when show to members is activated
  51 + Given the following communities
  52 + | name | identifier | owner |
  53 + | Free Software | freesoftware | joaosilva |
  54 + And the following users
  55 + | login | name |
  56 + | mario | Mario Souto |
  57 + | maria | Maria Silva |
  58 + And "Mario Souto" is a member of "Free Software"
  59 + And "Maria Silva" is a member of "Free Software"
  60 + And I am on freesoftware's control panel
  61 + And I follow "Manage Content"
  62 + And I should see "New content"
  63 + And I follow "New content"
  64 + And I should see "Folder"
  65 + When I follow "Folder"
  66 + And I fill in "Title" with "My Folder"
  67 + And I choose "article_published_false"
  68 + And I check "article_show_to_followers"
  69 + Then I should not see "Fill in the search"
  70 +
  71 + @selenium
50 72 Scenario: show exception users field when you choose the private option
51 73 Given the following communities
52 74 | name | identifier | owner |
... ...
lib/noosfero/plugin.rb
... ... @@ -417,6 +417,12 @@ class Noosfero::Plugin
417 417 nil
418 418 end
419 419  
  420 + # -> Adds adicional fields to a view
  421 + # returns = proc block that creates html code
  422 + def upload_files_extra_fields(article)
  423 + nil
  424 + end
  425 +
420 426 # -> Adds fields to the signup form
421 427 # returns = proc that creates html code
422 428 def signup_extra_contents
... ...
plugins/work_assignment/controllers/work_assignment_plugin_myprofile_controller.rb 0 → 100644
... ... @@ -0,0 +1,38 @@
  1 +class WorkAssignmentPluginMyprofileController < MyProfileController
  2 +
  3 +helper ArticleHelper
  4 +helper CmsHelper
  5 +
  6 +before_filter :protect_if, :only => [:edit_visibility]
  7 +
  8 +def edit_visibility
  9 + unless params[:article_id].blank?
  10 + folder = profile.environment.articles.find_by_id(params[:article_id])
  11 + @back_to = url_for(folder.parent.url)
  12 + unless params[:article].blank?
  13 + folder.published = params[:article][:published]
  14 + unless params[:q].nil?
  15 + folder.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i}
  16 + end
  17 + folder.save!
  18 + redirect_to @back_to
  19 + end
  20 + end
  21 + end
  22 +
  23 + def search_article_privacy_exceptions
  24 + arg = params[:q].downcase
  25 + result = profile.members.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"])
  26 + render :text => prepare_to_token_input(result).to_json
  27 + end
  28 +
  29 + protected
  30 +
  31 + def protect_if
  32 + article = environment.articles.find_by_id(params[:article_id])
  33 + render_access_denied unless (user && !article.nil? && (user.is_member_of? article.profile) &&
  34 + article.parent.allow_visibility_edition && article.folder? &&
  35 + (article.author == user || user.has_permission?('view_private_content', profile)))
  36 + end
  37 +
  38 +end
... ...
plugins/work_assignment/lib/ext/article.rb 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +require_dependency 'article'
  2 +
  3 +class Article
  4 + before_validation :work_assignment_save_into_author_folder
  5 + after_validation :work_assignment_change_visibility
  6 +
  7 + def work_assignment_save_into_author_folder
  8 + if not self.is_a? Folder and self.parent.kind_of? WorkAssignmentPlugin::WorkAssignment
  9 + author_folder = self.parent.find_or_create_author_folder(self.author)
  10 + self.name = WorkAssignmentPlugin::WorkAssignment.versioned_name(self, author_folder)
  11 + self.parent = author_folder
  12 + end
  13 + end
  14 +
  15 + def work_assignment_change_visibility
  16 + if self.parent && self.parent.parent && self.parent.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment)
  17 + self.published = self.parent.published
  18 + end
  19 + end
  20 +end
0 21 \ No newline at end of file
... ...
plugins/work_assignment/lib/ext/folder.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +require_dependency 'article'
  2 +require_dependency 'folder'
  3 +
  4 +class Folder < Article
  5 + after_save do |folder|
  6 + if folder.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment)
  7 + folder.children.each do |c|
  8 + c.published = folder.published
  9 + c.article_privacy_exceptions = folder.article_privacy_exceptions
  10 + end
  11 + end
  12 + end
  13 +end
... ...
plugins/work_assignment/lib/ext/uploaded_file.rb
... ... @@ -1,12 +0,0 @@
1   -require_dependency 'article'
2   -require_dependency 'uploaded_file'
3   -
4   -class UploadedFile < Article
5   - before_validation do |uploaded_file|
6   - if uploaded_file.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment)
7   - author_folder = uploaded_file.parent.find_or_create_author_folder(uploaded_file.author)
8   - uploaded_file.name = WorkAssignmentPlugin::WorkAssignment.versioned_name(uploaded_file, author_folder)
9   - uploaded_file.parent = author_folder
10   - end
11   - end
12   -end
plugins/work_assignment/lib/work_assignment_plugin.rb
... ... @@ -9,8 +9,8 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin
9 9 end
10 10  
11 11 def self.can_download_submission?(user, submission)
12   - work_assignment = submission.parent.parent
13   - work_assignment.publish_submissions || (user && (submission.author == user || user.has_permission?('view_private_content', work_assignment.profile)))
  12 + submission.published? || (user && (submission.author == user || user.has_permission?('view_private_content', submission.profile) ||
  13 + submission.display_unpublished_article_to?(user)))
14 14 end
15 15  
16 16 def self.is_submission?(content)
... ... @@ -37,7 +37,7 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin
37 37  
38 38 def content_viewer_controller_filters
39 39 block = proc do
40   - path = params[:page]
  40 + path = get_path(params[:page], params[:format])
41 41 content = profile.articles.find_by_path(path)
42 42  
43 43 if WorkAssignmentPlugin.is_submission?(content) && !WorkAssignmentPlugin.can_download_submission?(user, content)
... ... @@ -51,4 +51,34 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin
51 51 :block => block }
52 52 end
53 53  
  54 + def cms_controller_filters
  55 + block = proc do
  56 + if request.post? && params[:uploaded_files]
  57 + email_notification = params[:article_email_notification]
  58 + unless !email_notification || email_notification.empty?
  59 + email_contact = WorkAssignmentPlugin::EmailContact.new(:subject => @parent.name, :receiver => email_notification, :sender => user)
  60 + WorkAssignmentPlugin::EmailContact::EmailSender.build_mail_message(email_contact, @uploaded_files)
  61 + if email_contact.deliver
  62 + session[:notice] = _('Notification successfully sent')
  63 + else
  64 + session[:notice] = _('Notification not sent')
  65 + end
  66 + end
  67 + end
  68 + end
  69 +
  70 + { :type => 'after_filter',
  71 + :method_name => 'send_email_after_upload_file',
  72 + :options => {:only => 'upload_files'},
  73 + :block => block }
  74 + end
  75 +
  76 + def upload_files_extra_fields(article)
  77 + proc do
  78 + @article = Article.find_by_id(article)
  79 + if params[:parent_id] && !@article.nil? && @article.type == "WorkAssignmentPlugin::WorkAssignment"
  80 + render :partial => 'notify_text_field', :locals => { :size => '45'}
  81 + end
  82 + end
  83 + end
54 84 end
... ...
plugins/work_assignment/lib/work_assignment_plugin/email_contact.rb 0 → 100644
... ... @@ -0,0 +1,64 @@
  1 +class WorkAssignmentPlugin::EmailContact
  2 +
  3 + include ActiveModel::Validations
  4 +
  5 + def initialize(attributes = nil)
  6 + if attributes
  7 + attributes.each do |attr,value|
  8 + self.send("#{attr}=", value)
  9 + end
  10 + end
  11 + end
  12 +
  13 + attr_accessor :name
  14 + attr_accessor :subject
  15 + attr_accessor :message
  16 + attr_accessor :email
  17 + attr_accessor :receive_a_copy
  18 + attr_accessor :sender
  19 + attr_accessor :receiver
  20 +
  21 + N_('Subject'); N_('Message'); N_('e-Mail'); N_('Name')
  22 +
  23 + validates_presence_of :receiver, :subject, :message, :sender
  24 + validates_format_of :receiver, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|o| !o.email.blank?})
  25 +
  26 + def deliver
  27 + return false unless self.valid?
  28 + WorkAssignmentPlugin::EmailContact::EmailSender.notification(self).deliver
  29 + end
  30 +
  31 + class EmailSender < ActionMailer::Base
  32 +
  33 + def notification(email_contact)
  34 + name = email_contact.sender.name
  35 + email = email_contact.sender.email
  36 + message = email_contact.message
  37 + target = email_contact.receiver
  38 +
  39 + options = {
  40 + content_type: 'text/html',
  41 + to: target,
  42 + reply_to: email,
  43 + subject: email_contact.subject,
  44 + body: message,
  45 + from: "#{email_contact.sender.environment.name} <#{email_contact.sender.environment.contact_email}>",
  46 + }
  47 +
  48 + mail(options)
  49 + end
  50 +
  51 + def build_mail_message(email_contact, uploaded_files)
  52 + message = ""
  53 + if uploaded_files && uploaded_files.first && uploaded_files.first.parent && uploaded_files.first.parent.parent
  54 + article = uploaded_files.first.parent.parent
  55 + message = article.default_email + "<br>"
  56 + uploaded_files.each do |file|
  57 + url = url_for(file.url)
  58 + message += "<br><a href='#{url}'>#{url}</a>"
  59 + end
  60 + end
  61 + email_contact.message = message
  62 + end
  63 + end
  64 +end
... ...
plugins/work_assignment/lib/work_assignment_plugin/helper.rb
1 1 module WorkAssignmentPlugin::Helper
  2 + include CmsHelper
  3 +
2 4 def display_submissions(work_assignment, user)
3 5 return if work_assignment.submissions.empty?
4 6 content_tag('table',
... ... @@ -6,6 +8,7 @@ module WorkAssignmentPlugin::Helper
6 8 content_tag('th', c_('Author'), :style => 'width: 50%') +
7 9 content_tag('th', _('Submission date')) +
8 10 content_tag('th', _('Versions'), :style => 'text-align: center') +
  11 + content_tag('th', '') +
9 12 content_tag('th', '')
10 13 ).html_safe +
11 14 work_assignment.children.map {|author_folder| display_author_folder(author_folder, user)}.join("\n").html_safe
... ... @@ -18,7 +21,8 @@ module WorkAssignmentPlugin::Helper
18 21 content_tag('td', link_to_last_submission(author_folder, user)) +
19 22 content_tag('td', time_format(author_folder.children.last.created_at)) +
20 23 content_tag('td', author_folder.children.count, :style => 'text-align: center') +
21   - content_tag('td', content_tag('button', _('View all versions'), :class => 'view-author-versions', 'data-folder-id' => author_folder.id))
  24 + content_tag('td', content_tag('button', _('View all versions'), :class => 'view-author-versions', 'data-folder-id' => author_folder.id)) +
  25 + content_tag('td', display_privacy_button(author_folder, user))
22 26 ).html_safe +
23 27 author_folder.children.map {|submission| display_submission(submission, user)}.join("\n").html_safe
24 28 end
... ... @@ -26,7 +30,13 @@ module WorkAssignmentPlugin::Helper
26 30 def display_submission(submission, user)
27 31 content_tag('tr',
28 32 content_tag('td', link_to_submission(submission, user)) +
29   - content_tag('td', time_format(submission.created_at), :colspan => 3),
  33 + content_tag('td', time_format(submission.created_at))+
  34 + content_tag('td', '') +
  35 + content_tag('td',
  36 + if submission.parent.parent.allow_post_content?(user)
  37 + display_delete_button(submission)
  38 + end
  39 + ),
30 40 :class => "submission-from-#{submission.parent.id}",
31 41 :style => 'display: none'
32 42 )
... ... @@ -40,7 +50,6 @@ module WorkAssignmentPlugin::Helper
40 50 end
41 51 end
42 52  
43   -
44 53 def link_to_last_submission(author_folder, user)
45 54 if WorkAssignmentPlugin.can_download_submission?(user, author_folder.children.last)
46 55 link_to(author_folder.name, author_folder.children.last.url)
... ... @@ -48,6 +57,7 @@ module WorkAssignmentPlugin::Helper
48 57 author_folder.name
49 58 end
50 59 end
  60 +
51 61 # FIXME Copied from custom-froms. Consider passing it to core...
52 62 def time_format(time)
53 63 minutes = (time.min == 0) ? '' : ':%M'
... ... @@ -56,4 +66,28 @@ module WorkAssignmentPlugin::Helper
56 66 time.strftime("%Y-%m-%d#{hour+minutes+h}")
57 67 end
58 68  
  69 + def display_delete_button(article)
  70 + expirable_button article, :delete, _('Delete'),
  71 + {:controller =>'cms', :action => 'destroy', :id => article.id },
  72 + :method => :post, :confirm => delete_article_message(article)
  73 + end
  74 +
  75 + def display_privacy_button(author_folder, user)
  76 + folder = environment.articles.find_by_id(author_folder.id)
  77 + work_assignment = folder.parent
  78 + @back_to = url_for(work_assignment.url)
  79 +
  80 + if(user && work_assignment.allow_visibility_edition &&
  81 + ((author_folder.author_id == user.id && (user.is_member_of? profile)) ||
  82 + user.has_permission?('view_private_content', profile)))
  83 +
  84 + @tokenized_children = prepare_to_token_input(
  85 + profile.members.includes(:articles_with_access).find_all{ |m|
  86 + m.articles_with_access.include?(folder)
  87 + })
  88 + button :edit, _('Edit'), { :controller => 'work_assignment_plugin_myprofile',
  89 + :action => 'edit_visibility', :article_id => folder.id,
  90 + :tokenized_children => @tokenized_children, :back_to => @back_to}, :method => :post
  91 + end
  92 + end
59 93 end
... ...
plugins/work_assignment/lib/work_assignment_plugin/work_assignment.rb
1 1 class WorkAssignmentPlugin::WorkAssignment < Folder
2 2  
3 3 settings_items :publish_submissions, :type => :boolean, :default => false
  4 + settings_items :default_email, :type => :string, :default => ""
  5 + settings_items :allow_visibility_edition, :type => :boolean, :default => false
4 6  
5 7 attr_accessible :publish_submissions
6   -
  8 + attr_accessible :default_email
  9 + attr_accessible :allow_visibility_edition
  10 +
7 11 def self.icon_name(article = nil)
8 12 'work-assignment'
9 13 end
... ... @@ -29,13 +33,22 @@ class WorkAssignmentPlugin::WorkAssignment &lt; Folder
29 33 end
30 34  
31 35 def to_html(options = {})
32   - proc do
  36 + lambda do
33 37 render :file => 'content_viewer/work_assignment.html.erb'
34 38 end
35 39 end
36 40  
37 41 def find_or_create_author_folder(author)
38   - children.find_by_slug(author.name.to_slug) || Folder.create!(:name => author.name, :parent => self, :profile => profile)
  42 + children.find_by_slug(author.name.to_slug) || Folder.create!(
  43 + {
  44 + :name => author.name,
  45 + :parent => self,
  46 + :profile => profile,
  47 + :author => author,
  48 + :published => publish_submissions,
  49 + },
  50 + :without_protection => true
  51 + )
39 52 end
40 53  
41 54 def submissions
... ... @@ -45,6 +58,5 @@ class WorkAssignmentPlugin::WorkAssignment &lt; Folder
45 58 def cache_key_with_person(params = {}, user = nil, language = 'en')
46 59 cache_key_without_person + (user && profile.members.include?(user) ? "-#{user.identifier}" : '')
47 60 end
48   - alias_method_chain :cache_key, :person
49   -
  61 + alias_method_chain :cache_key, :person
50 62 end
... ...
plugins/work_assignment/test/functional/cms_controller_test.rb
1   -require 'test_helper'
  1 +require File.expand_path(File.dirname(__FILE__) + "/../../../../test/test_helper")
2 2 require 'cms_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ... @@ -12,33 +12,67 @@ class CmsControllerTest &lt; ActionController::TestCase
12 12 @response = ActionController::TestResponse.new
13 13 @person = create_user('test_user').person
14 14 login_as :test_user
  15 + e = Environment.default
  16 + e.enabled_plugins = ['WorkAssignmentPlugin']
  17 + e.save!
  18 + @organization = fast_create(Organization) #
15 19 end
16 20  
17   - attr_accessor :person
18   -
19 21 should 'not allow non-members to upload submissions on work_assignment' do
20   - organization = fast_create(Organization)
21   - work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization)
22   -
23   - get :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id
  22 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, nil)
  23 + get :upload_files, :profile => @organization.identifier, :parent_id => work_assignment.id
24 24 assert_response :forbidden
25 25 assert_template 'access_denied'
  26 + end
26 27  
27   - organization.add_member(person)
28   -
29   - get :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id
  28 + should 'allow members to upload submissions on work_assignment' do
  29 + @organization.add_member(@person)
  30 + # then he trys to upload new stuff
  31 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, nil)
  32 + get :upload_files, :profile => @organization.identifier, :parent_id => work_assignment.id
30 33 assert_response :success
31 34 end
32 35  
  36 + should 'redirect to Work Assignment view page after upload submission' do
  37 + @organization.add_member(@person)
  38 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, nil)
  39 + post :upload_files, :profile => @organization.identifier, :parent_id => work_assignment.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] , :back_to => @work_assignment.url
  40 + assert_redirected_to work_assignment.url
  41 + end
  42 +
33 43 should 'upload submission and automatically move it to the author folder' do
34   - organization = fast_create(Organization)
35   - work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization)
36   - organization.add_member(person)
37   - post :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')]
  44 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, nil)
  45 + @organization.add_member(@person)
  46 + post :upload_files, :profile => @organization.identifier, :parent_id => work_assignment.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')]
  47 + submission = UploadedFile.last
  48 + assert_equal work_assignment.find_or_create_author_folder(@person), submission.parent
  49 + end
  50 +
  51 + should 'work_assignment attribute allow_visibility_edition is true when set a new work_assignment' do
  52 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, true)
  53 + @organization.add_member(@person)
  54 + assert_equal true, work_assignment.allow_visibility_edition
  55 + end
38 56  
  57 + should 'a submission and parent attribute "published" be equal to Work Assignment attribute publish submissions' do
  58 + @organization.add_member(@person)
  59 + work_assignment = create_work_assignment('Work Assignment', @organization, true, nil)
  60 + assert_equal true, work_assignment.publish_submissions
  61 + post :upload_files, :profile => @organization.identifier, :parent_id => work_assignment.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')]
39 62 submission = UploadedFile.last
40   - assert_equal work_assignment.find_or_create_author_folder(person), submission.parent
  63 + assert_equal work_assignment.publish_submissions, submission.published
  64 + assert_equal work_assignment.publish_submissions, submission.parent.published
  65 +
  66 + other_work_assignment = create_work_assignment('Other Work Assigment', @organization, false, nil)
  67 + assert_equal false, other_work_assignment.publish_submissions
  68 + post :upload_files, :profile => @organization.identifier, :parent_id => other_work_assignment.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')]
  69 + submission = UploadedFile.last
  70 + assert_equal other_work_assignment.publish_submissions, submission.published
  71 + assert_equal other_work_assignment.publish_submissions, submission.parent.published
41 72 end
42 73  
  74 + private
  75 + def create_work_assignment(name = nil, profile = nil, publish_submissions = nil, allow_visibility_edition = nil)
  76 + @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => name, :profile => profile, :publish_submissions => publish_submissions, :allow_visibility_edition => allow_visibility_edition)
  77 + end
43 78 end
44   -
... ...
plugins/work_assignment/test/functional/content_viewer_controller_test.rb
1   -require 'test_helper'
  1 +require File.expand_path(File.dirname(__FILE__) + "/../../../../test/test_helper")
2 2 require 'content_viewer_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ... @@ -15,6 +15,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
15 15 @organization = fast_create(Organization)
16 16 @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => @organization)
17 17 @person = create_user('test_user').person
  18 + @organization.add_member(@person)
18 19 @environment = @organization.environment
19 20 @environment.enable_plugin(WorkAssignmentPlugin)
20 21 @environment.save!
... ... @@ -23,19 +24,17 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
23 24 attr_reader :organization, :person, :profile, :work_assignment
24 25  
25 26 should 'can download work_assignment' do
26   - random_member = fast_create(Person)
27   - organization.add_member(random_member)
28   - folder = work_assignment.find_or_create_author_folder(random_member)
  27 + folder = work_assignment.find_or_create_author_folder(@person)
29 28 submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder)
30 29 WorkAssignmentPlugin.stubs(:can_download_submission?).returns(false)
31 30  
32   - get :view_page, :profile => organization.identifier, :page => submission.path
  31 + get :view_page, :profile => @organization.identifier, :page => submission.path
33 32 assert_response :forbidden
34 33 assert_template 'access_denied'
35 34  
36 35 WorkAssignmentPlugin.stubs(:can_download_submission?).returns(true)
37 36  
38   - get :view_page, :profile => organization.identifier, :page => submission.path
  37 + get :view_page, :profile => @organization.identifier, :page => submission.path
39 38 assert_response :success
40 39 end
41 40  
... ...
plugins/work_assignment/test/functional/work_assignment_plugin_myprofile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,191 @@
  1 +require File.expand_path(File.dirname(__FILE__) + "/../../../../test/test_helper")
  2 +require 'work_assignment_plugin_myprofile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class WorkAssignmentPluginMyprofileController; def rescue_action(e) raise e end; end
  6 +
  7 +class WorkAssignmentPluginMyprofileControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = WorkAssignmentPluginMyprofileController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 + @person = create_user('test_user').person
  14 + login_as :test_user
  15 + e = Environment.default
  16 + e.enabled_plugins = ['WorkAssignmentPlugin']
  17 + e.save!
  18 + @organization = fast_create(Organization) #
  19 + end
  20 +
  21 + should 'submission edit visibility deny access to users and admin when Work Assignment allow_visibility_edition is false' do
  22 + @organization.add_member(@person)
  23 + ##### Testing with normal user
  24 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, false)
  25 + work_assignment.save!
  26 + assert_equal false, work_assignment.allow_visibility_edition
  27 + parent = work_assignment.find_or_create_author_folder(@person)
  28 + UploadedFile.create(
  29 + {
  30 + :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'),
  31 + :profile => @organization,
  32 + :parent => parent,
  33 + :last_changed_by => @person,
  34 + :author => @person,
  35 + },
  36 + :without_protection => true
  37 + )
  38 + submission = UploadedFile.find_by_filename("test.txt")
  39 + assert_equal false, submission.published
  40 + assert_equal false, submission.parent.published
  41 +
  42 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id
  43 + assert_template 'access_denied'
  44 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id, :article => { :published => true }
  45 + assert_template 'access_denied'
  46 +
  47 + submission.reload
  48 + assert_equal false, submission.published
  49 + assert_equal false, submission.parent.published
  50 +
  51 + #### Even with admin user
  52 + e = Environment.default
  53 + assert_equal false, @person.is_admin?
  54 + e.add_admin(@person)
  55 + e.save!
  56 + assert_equal true, @person.is_admin?
  57 +
  58 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id
  59 + assert_template 'access_denied'
  60 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id, :article => { :published => true }
  61 + assert_template 'access_denied'
  62 +
  63 + submission.reload
  64 + assert_equal false, submission.published
  65 + end
  66 +
  67 + should 'redirect an unlogged user to the login page if he tryes to access the edit visibility page and work_assignment allow_visibility_edition is true' do
  68 + @organization.add_member(@person)
  69 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, true)
  70 + assert_equal true, work_assignment.allow_visibility_edition
  71 + work_assignment.save!
  72 + parent = work_assignment.find_or_create_author_folder(@person)
  73 + UploadedFile.create(
  74 + {
  75 + :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'),
  76 + :profile => @organization,
  77 + :parent => parent,
  78 + :last_changed_by => @person,
  79 + :author => @person,
  80 + },
  81 + :without_protection => true
  82 + )
  83 + logout
  84 + submission = UploadedFile.find_by_filename("test.txt")
  85 + assert_equal false, submission.parent.published
  86 + assert_equal false, submission.published
  87 +
  88 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id
  89 + assert_redirected_to '/account/login'
  90 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id, :article => { :published => true }
  91 + assert_redirected_to '/account/login'
  92 + submission.reload
  93 + assert_equal false, submission.parent.published
  94 + assert_equal false, submission.published
  95 + end
  96 +
  97 + should 'submission edit_visibility deny access to not owner when WorkAssignment edit_visibility is true' do
  98 + @organization.add_member(@person) # current_user is a member
  99 + work_assignment = create_work_assignment('Another Work Assignment', @organization, nil, true)
  100 + parent = work_assignment.find_or_create_author_folder(@person)
  101 + UploadedFile.create(
  102 + {
  103 + :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'),
  104 + :profile => @organization,
  105 + :parent => parent,
  106 + :last_changed_by => @person,
  107 + :author => @person,
  108 + },
  109 + :without_protection => true
  110 + )
  111 + logout
  112 +
  113 +
  114 + other_person = create_user('other_user').person
  115 + @organization.add_member(other_person)
  116 + login_as :other_user
  117 +
  118 + @organization.add_member(other_person)
  119 + submission = UploadedFile.find_by_filename("test.txt")
  120 + assert_equal(submission.author, @person)
  121 +
  122 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id
  123 + assert_template 'access_denied'
  124 +
  125 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id, :article => { :published => true }
  126 + assert_template 'access_denied'
  127 +
  128 + submission.reload
  129 + assert_equal false, submission.parent.published
  130 + assert_equal false, submission.published
  131 + end
  132 +
  133 + should 'submission white list give permission to an user that has been added' do
  134 + other_person = create_user('other_user').person
  135 + @organization.add_member(@person)
  136 + @organization.add_member(other_person)
  137 + work_assignment = create_work_assignment('Another Work Assignment', @organization, false, true)
  138 + parent = work_assignment.find_or_create_author_folder(@person)
  139 + UploadedFile.create(
  140 + {
  141 + :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'),
  142 + :profile => @organization,
  143 + :parent => parent,
  144 + :last_changed_by => @person,
  145 + :author => @person,
  146 + },
  147 + :without_protection => true
  148 + )
  149 + submission = UploadedFile.find_by_filename("test.txt")
  150 + assert_equal false, submission.article_privacy_exceptions.include?(other_person)
  151 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id, :article => { :published => false }, :q => other_person.id
  152 + submission.reload
  153 + assert_equal true, submission.parent.article_privacy_exceptions.include?(other_person)
  154 + assert_equal true, submission.article_privacy_exceptions.include?(other_person)
  155 + end
  156 +
  157 + should 'submission edit_visibility deny access to owner if not organization member' do
  158 + @organization.add_member(@person) # current_user is a member
  159 + work_assignment = create_work_assignment('Work Assignment', @organization, nil, true)
  160 + parent = work_assignment.find_or_create_author_folder(@person)
  161 + UploadedFile.create(
  162 + {
  163 + :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'),
  164 + :profile => @organization,
  165 + :parent => parent,
  166 + :last_changed_by => @person,
  167 + :author => @person,
  168 + },
  169 + :without_protection => true
  170 + )
  171 + @organization.remove_member(@person)
  172 + submission = UploadedFile.find_by_filename("test.txt")
  173 +
  174 + assert_equal false, (@person.is_member_of? submission.profile)
  175 +
  176 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id
  177 + assert_template 'access_denied'
  178 +
  179 + post :edit_visibility, :profile => @organization.identifier, :article_id => parent.id, :article => { :published => true }
  180 + assert_template 'access_denied'
  181 +
  182 + submission.reload
  183 + assert_equal false, submission.parent.published
  184 + assert_equal false, submission.published
  185 + end
  186 +
  187 + private
  188 + def create_work_assignment(name = nil, profile = nil, publish_submissions = nil, allow_visibility_edition = nil)
  189 + @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => name, :profile => profile, :publish_submissions => publish_submissions, :allow_visibility_edition => allow_visibility_edition)
  190 + end
  191 +end
... ...
plugins/work_assignment/test/unit/work_assingment_plugin/work_assignment_test.rb
1   -require "test_helper"
  1 +require File.expand_path(File.dirname(__FILE__) + "/../../../../../test/test_helper")
2 2  
3 3 class WorkAssignmentTest < ActiveSupport::TestCase
4 4 should 'find or create sub-folder based on author identifier' do
... ...
plugins/work_assignment/test/unit/work_assingment_plugin_test.rb
1   -require 'test_helper'
  1 +require File.expand_path(File.dirname(__FILE__) + "/../../../../test/test_helper")
2 2  
3 3 class WorkAssignmentPluginTest < ActiveSupport::TestCase
4 4 should 'verify if a content is a work_assignment submission' do
5 5 organization = fast_create(Organization)
6   - content = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :author => fast_create(Person))
  6 + folder = fast_create(Folder)
  7 + person = fast_create(Person)
  8 + content = UploadedFile.create(
  9 + {
  10 + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'),
  11 + :profile => organization,
  12 + :parent => folder,
  13 + :last_changed_by => person,
  14 + :author => person,
  15 + },
  16 + :without_protection => true
  17 + )
7 18 assert !WorkAssignmentPlugin.is_submission?(content)
8 19  
9 20 work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization)
... ... @@ -22,7 +33,9 @@ class WorkAssignmentPluginTest &lt; ActiveSupport::TestCase
22 33 work_assignment = submission.parent.parent
23 34 work_assignment.publish_submissions = true
24 35 work_assignment.save!
25   - assert WorkAssignmentPlugin.can_download_submission?(nil, submission)
  36 +
  37 + other_submission = create_submission(nil, work_assignment)
  38 + assert WorkAssignmentPlugin.can_download_submission?(nil, other_submission)
26 39 end
27 40  
28 41 should 'be able to download submission if the user is author of it' do
... ... @@ -45,12 +58,21 @@ class WorkAssignmentPluginTest &lt; ActiveSupport::TestCase
45 58  
46 59 private
47 60  
48   - def create_submission(author=nil)
  61 + def create_submission(author=nil, work_assignment=nil)
49 62 author ||= fast_create(Person)
50 63 organization = fast_create(Organization)
51   -
52   - work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization)
  64 + organization.add_member(author)
  65 + work_assignment ||= WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization)
53 66 author_folder = work_assignment.find_or_create_author_folder(author)
54   - create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => author_folder, :author => author, :last_changed_by => author)
  67 + content = UploadedFile.create(
  68 + {
  69 + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'),
  70 + :profile => organization,
  71 + :parent => author_folder,
  72 + :last_changed_by => author,
  73 + :author => author,
  74 + },
  75 + :without_protection => true
  76 + )
55 77 end
56 78 end
... ...
plugins/work_assignment/views/cms/_notify_text_field.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<h5><%= _('If you want to notify someone about this action, fill the field below with the emails of the destinies, separated by comma.') %></h5>
  2 +
  3 +<%= labelled_text_field(_('Send notification to: '), 'article_email_notification', user.email, :style => 'width: 60%;') %>
... ...
plugins/work_assignment/views/cms/work_assignment_plugin/_work_assignment.html.erb
1 1 <%= render :partial => 'folder', :locals => {:f => f} %>
2 2  
3   -<%= labelled_check_box(_('Publish submissions'), 'article[publish_submissions]', true, @article.publish_submissions) %>
  3 +<%= labelled_form_field(_('Default email message:'), text_area(:article, :default_email, :rows => 3, :cols => 64)) %>
  4 +
  5 +<%=labelled_check_box(_('Publish submissions'), 'article[publish_submissions]', true, @article.publish_submissions) %>
  6 +
  7 +<%=labelled_check_box(_('Allow users change submissions privacy?'), 'article[allow_visibility_edition]', true, @article.allow_visibility_edition) %>
... ...
plugins/work_assignment/views/work_assignment_plugin_myprofile/edit_visibility.html.erb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<div class="select-visibility-options">
  2 +
  3 +<%= labelled_form_for 'article', :html => { :multipart => true, :class => @type } do |f| %>
  4 +
  5 + <% @article = environment.articles.find_by_id((params[:article_id]))%>
  6 +
  7 + <% @tokenized_children = params[:tokenized_children]%>
  8 +
  9 + <%= hidden_field_tag('article_id', @article.id) %>
  10 +
  11 + <div id='edit-article-options'>
  12 + <%= visibility_options(@article, @tokenized_children) %>
  13 + </div>
  14 +
  15 + <% button_bar do %>
  16 + <%= submit_button :save, _('Save') %>
  17 + <%= button :cancel, _('Cancel'), @back_to %>
  18 + <% end %>
  19 +<% end %>
  20 +</div>
  21 +
  22 +<br style='clear: both'/>
  23 +
  24 +<%= javascript_include_tag "article.js" %>
... ...
public/javascripts/article.js
... ... @@ -136,7 +136,7 @@ jQuery(function($) {
136 136 if (data.length && data.length > 0) {
137 137 $('#media-search-results').slideDown();
138 138 }
139   - $('#media-search-box .header').toggleClass('icon-loading');
  139 + $('#media-search-box .header').toggleClass('icon-loading');
140 140 });
141 141 return false;
142 142 });
... ... @@ -144,20 +144,20 @@ jQuery(function($) {
144 144 $('#media-upload-form form').ajaxForm({
145 145 resetForm: true,
146 146 beforeSubmit:
147   - function() {
148   - $('#media-upload-form').slideUp();
149   - $('#media-upload-box .header').toggleClass('icon-loading');
150   - },
  147 + function() {
  148 + $('#media-upload-form').slideUp();
  149 + $('#media-upload-box .header').toggleClass('icon-loading');
  150 + },
151 151 success:
152   - function(text) {
153   - text = text.replace('<pre>', '').replace('</pre>', ''); // old firefox
154   - var data = $.parseJSON(text);
155   - list_items(data, '#media-upload-results .items', true);
156   - if (data.length && data.length > 0) {
157   - $('#media-upload-results').slideDown();
158   - }
159   - $('#media-upload-box .header').toggleClass('icon-loading');
  152 + function(text) {
  153 + text = text.replace('<pre>', '').replace('</pre>', ''); // old firefox
  154 + var data = $.parseJSON(text);
  155 + list_items(data, '#media-upload-results .items', true);
  156 + if (data.length && data.length > 0) {
  157 + $('#media-upload-results').slideDown();
160 158 }
  159 + $('#media-upload-box .header').toggleClass('icon-loading');
  160 + }
161 161 });
162 162  
163 163 $('#media-upload-more-files').click(function() {
... ... @@ -166,19 +166,45 @@ jQuery(function($) {
166 166 return false;
167 167 });
168 168  
  169 + function is_public_article() {
  170 + return $("#article_published_true").attr('checked');
  171 + }
  172 +
  173 + function show_hide_privacy_options() {
  174 + var show_privacy_options = $("#article_published_false").attr('checked');
  175 + var custom_privacy_option = $(".custom_privacy_option").parent("div");
  176 +
  177 + if( show_privacy_options ) {
  178 + custom_privacy_option.show();
  179 + } else {
  180 + custom_privacy_option.hide();
  181 + }
  182 + show_hide_token_input();
  183 + }
  184 +
169 185 function show_hide_token_input() {
170   - if($("#article_published_false").attr('checked'))
171   - $("#text-input-search-exception-users").parent("div").css('display', 'block');
172   - else
173   - $("#text-input-search-exception-users").parent("div").css('display', 'none');
  186 + var display_token = $(".custom_privacy_option:checked").length == 0;
  187 + var token_field = $("#text-input-search-exception-users").parent("div");
  188 +
  189 + if( display_token && !is_public_article() ) {
  190 + token_field.css('display', 'block');
  191 + } else {
  192 + token_field.css('display', 'none');
  193 + }
174 194 }
175 195  
176 196 if( $("#token-input-search-article-privacy-exceptions").length == 1 ) {
  197 + show_hide_privacy_options();
177 198 show_hide_token_input();
178   -
179   - //Hide / Show the text area
180   - $("#article_published_false").click(show_hide_token_input);
181   - $("#article_published_true").click(show_hide_token_input);
182 199 }
183 200  
  201 + $(document).ready(function(){
  202 + show_hide_privacy_options();
  203 + });
  204 +
  205 + //Hide / Show the text area
  206 + $("#article_published_false").click(show_hide_privacy_options);
  207 + $("#article_published_true").click(show_hide_privacy_options);
  208 + $(".custom_privacy_option").click(show_hide_token_input);
  209 +
184 210 });
... ...
test/functional/account_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'account_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/admin_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'admin_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/admin_panel_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'admin_panel_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/application_controller_test.rb
1 1 # encoding: UTF-8
2   -require File.dirname(__FILE__) + '/../test_helper'
  2 +require_relative "../test_helper"
3 3 require 'test_controller'
4 4  
5 5 # Re-raise errors caught by the controller.
... ...
test/functional/catalog_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'catalog_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/categories_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'categories_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/chat_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class ChatControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/cms_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'cms_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ... @@ -101,12 +101,26 @@ class CmsControllerTest &lt; ActionController::TestCase
101 101 assert_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"}
102 102 end
103 103  
  104 + should 'display the profile homepage if logged user is an environment admin' do
  105 + env = Environment.default; env.enable('cant_change_homepage'); env.save!
  106 + env.add_admin(profile)
  107 + get :index, :profile => profile.identifier
  108 + assert_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"}
  109 + end
  110 +
104 111 should 'not display the profile homepage if cannot change homepage' do
105 112 env = Environment.default; env.enable('cant_change_homepage')
106 113 get :index, :profile => profile.identifier
107 114 assert_no_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"}
108 115 end
109 116  
  117 + should 'not allow profile homepage changes if cannot change homepage' do
  118 + env = Environment.default; env.enable('cant_change_homepage')
  119 + a = profile.articles.create!(:name => 'my new home page')
  120 + post :set_home_page, :profile => profile.identifier, :id => a.id
  121 + assert_response 403
  122 + end
  123 +
110 124 should 'be able to set home page' do
111 125 a = profile.articles.build(:name => 'my new home page')
112 126 a.save!
... ...
test/functional/comment_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'comment_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/contact_controller_test.rb
1 1 # encoding: UTF-8
2   -require File.dirname(__FILE__) + '/../test_helper'
  2 +require_relative "../test_helper"
3 3 require 'contact_controller'
4 4  
5 5 # Re-raise errors caught by the controller.
... ...
test/functional/content_viewer_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'content_viewer_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ... @@ -661,8 +661,8 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
661 661 get :view_page, :profile => owner.identifier, :page => folder.path
662 662 assert_response :success
663 663 assert_select '.image-gallery-item', 0
664   - end
665   -
  664 + end
  665 +
666 666  
667 667 should 'display default image in the slideshow if thumbnails were not processed' do
668 668 @controller.stubs(:per_page).returns(1)
... ... @@ -1296,14 +1296,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1296 1296 def comment_form_extra_contents(args)
1297 1297 proc {
1298 1298 hidden_field_tag('comment[some_field_id]', 1)
1299   - }
  1299 + }
1300 1300 end
1301 1301 end
1302 1302 class Plugin2 < Noosfero::Plugin
1303 1303 def comment_form_extra_contents(args)
1304 1304 proc {
1305 1305 hidden_field_tag('comment[another_field_id]', 1)
1306   - }
  1306 + }
1307 1307 end
1308 1308 end
1309 1309 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
... ... @@ -1373,20 +1373,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1373 1373 get :view_page, :profile => profile.identifier, :page => [blog.path]
1374 1374 assert_tag :tag => 'strong', :content => /bold/
1375 1375 end
1376   -
  1376 +
1377 1377 should 'add extra content on article header from plugins' do
1378 1378 class Plugin1 < Noosfero::Plugin
1379 1379 def article_header_extra_contents(args)
1380 1380 proc {
1381 1381 content_tag('div', '', :class => 'plugin1')
1382   - }
  1382 + }
1383 1383 end
1384 1384 end
1385 1385 class Plugin2 < Noosfero::Plugin
1386 1386 def article_header_extra_contents(args)
1387 1387 proc {
1388 1388 content_tag('div', '', :class => 'plugin2')
1389   - }
  1389 + }
1390 1390 end
1391 1391 end
1392 1392 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
... ... @@ -1447,4 +1447,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1447 1447 assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ }
1448 1448 end
1449 1449  
  1450 + should 'manage private article visualization' do
  1451 + community = Community.create(:name => 'test-community')
  1452 + community.add_member(@profile)
  1453 + community.save!
  1454 +
  1455 + blog = community.articles.find_by_name("Blog")
  1456 +
  1457 + article = TinyMceArticle.create(:name => 'Article to be shared with images',
  1458 + :body => 'This article should be shared with all social networks',
  1459 + :profile => @profile,
  1460 + :published => false,
  1461 + :show_to_followers => true)
  1462 + article.parent = blog
  1463 + article.save!
  1464 +
  1465 + otheruser = create_user('otheruser').person
  1466 + community.add_member(otheruser)
  1467 + login_as(otheruser.identifier)
  1468 +
  1469 + get :view_page, :profile => community.identifier, "page" => 'blog'
  1470 +
  1471 + assert_response :success
  1472 + assert_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
  1473 +
  1474 + article.show_to_followers = false
  1475 + article.save!
  1476 +
  1477 + get :view_page, :profile => community.identifier, "page" => 'blog'
  1478 +
  1479 + assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
  1480 + end
1450 1481 end
... ...
test/functional/doc_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class DocControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/edit_template_controller_test.rb
1 1 # FIXME: this tests must me moved into design plugin
2 2  
3   -require File.dirname(__FILE__) + '/../test_helper'
  3 +require_relative "../test_helper"
4 4 require 'edit_template_controller'
5 5  
6 6 # Re-raise errors caught by the controller.
... ...
test/functional/embed_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class EmbedControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/enterprise_registration_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'enterprise_registration_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/enterprise_validation_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'enterprise_validation_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/environment_design_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'environment_design_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/environment_role_manager_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'environment_role_manager_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/environment_themes_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class EnvironmentThemesController; def rescue_action(e) raise e end; end
4 4  
... ...
test/functional/events_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class EventsControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/favorite_enterprises_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'favorite_enterprises_controller'
3 3  
4 4 class FavoriteEnterprisesController; def rescue_action(e) raise e end; end
... ...
test/functional/features_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'features_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/friends_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'friends_controller'
3 3  
4 4 class FriendsController; def rescue_action(e) raise e end; end
... ...
test/functional/home_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'home_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/invite_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class InviteControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/licenses_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'licenses_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/mailconf_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class MailconfControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/manage_products_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'manage_products_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/map_balloon_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'map_balloon_controller'
3 3  
4 4  
... ...
test/functional/maps_controller_test.rb
1 1 # encoding: UTF-8
2   -require File.dirname(__FILE__) + '/../test_helper'
  2 +require_relative "../test_helper"
3 3 require 'maps_controller'
4 4  
5 5 # Re-raise errors caught by the controller.
... ...
test/functional/memberships_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'memberships_controller'
3 3  
4 4  
... ...
test/functional/my_profile_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'my_profile_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/plugin_admin_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class PluginAdminController
4 4 def index
... ...
test/functional/plugins_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'plugins_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/profile_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'profile_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/profile_design_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'profile_design_controller'
3 3  
4 4 class ProfileDesignController; def rescue_action(e) raise e end; end
... ... @@ -737,4 +737,22 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
737 737 end
738 738 end
739 739  
  740 + test 'should forbid POST to save for fixed blocks' do
  741 + block = profile.blocks.last
  742 + block.fixed = true
  743 + block.save!
  744 +
  745 + post :save, id: block.id, profile: profile.identifier
  746 + assert_response :forbidden
  747 + end
  748 +
  749 + test 'should forbid POST to move_block for fixed blocks' do
  750 + block = profile.blocks.last
  751 + block.fixed = true
  752 + block.save!
  753 +
  754 + post :move_block, id: block.id, profile: profile.identifier, target: "end-of-box-#{@box3.id}"
  755 + assert_response :forbidden
  756 + end
  757 +
740 758 end
... ...
test/functional/profile_editor_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'profile_editor_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/profile_members_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'profile_members_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/profile_search_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'profile_search_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/profile_themes_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 # require 'profile_themes_controller'
3 3  
4 4 class ProfileThemesController; def rescue_action(e) raise e end; end
... ...
test/functional/public_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'public_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/region_validators_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'region_validators_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/role_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'role_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/search_controller_test.rb
1 1 # encoding: UTF-8
2   -require File.dirname(__FILE__) + '/../test_helper'
  2 +require_relative "../test_helper"
3 3 require 'search_controller'
4 4  
5 5 # Re-raise errors caught by the controller.
... ...
test/functional/spam_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2  
3 3 class SpamControllerTest < ActionController::TestCase
4 4  
... ...
test/functional/system_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'system_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/tasks_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'tasks_controller'
3 3  
4 4 class TasksController; def rescue_action(e) raise e end; end
... ...
test/functional/templates_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'templates_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/trusted_sites_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'trusted_sites_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/functional/users_controller_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require_relative "../test_helper"
2 2 require 'users_controller'
3 3  
4 4 # Re-raise errors caught by the controller.
... ...
test/integration/approve_reject_enterprise_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class ApproveRejectEnterpriseTest < ActionController::IntegrationTest
4 4 all_fixtures
... ...
test/integration/assets_menu_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class AssetsMenuTest < ActionController::IntegrationTest
4 4  
... ...
test/integration/assigning_validator_organizations_to_regions_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class AssigningValidatorOrganizationsToRegionsTest < ActionController::IntegrationTest
4 4  
... ...
test/integration/blocks_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class BlocksTest < ActionController::IntegrationTest
4 4 def blog_on_article_block_bootstrap
... ...
test/integration/categories_menu_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class CategoriesMenuTest < ActionController::IntegrationTest
4 4  
... ...
test/integration/controller_naming_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class ControllerNamingTest < ActionController::IntegrationTest
4 4  
... ...
test/integration/editing_person_info_test.rb
1   -require "#{File.dirname(__FILE__)}/../test_helper"
  1 +require_relative "../test_helper"
2 2  
3 3 class EditingPersonInfoTest < ActionController::IntegrationTest
4 4  
... ...