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,6 +174,8 @@ class CmsController < MyProfileController
174 174
175 post_only :set_home_page 175 post_only :set_home_page
176 def set_home_page 176 def set_home_page
  177 + return render_access_denied unless user.can_change_homepage?
  178 +
177 article = params[:id].nil? ? nil : profile.articles.find(params[:id]) 179 article = params[:id].nil? ? nil : profile.articles.find(params[:id])
178 profile.update_attribute(:home_page, article) 180 profile.update_attribute(:home_page, article)
179 181
@@ -212,6 +214,7 @@ class CmsController < MyProfileController @@ -212,6 +214,7 @@ class CmsController < MyProfileController
212 if @errors.any? 214 if @errors.any?
213 render :action => 'upload_files', :parent_id => @parent_id 215 render :action => 'upload_files', :parent_id => @parent_id
214 else 216 else
  217 + session[:notice] = _('File(s) successfully uploaded')
215 if @back_to 218 if @back_to
216 redirect_to @back_to 219 redirect_to @back_to
217 elsif @parent 220 elsif @parent
app/controllers/my_profile/profile_design_controller.rb
@@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController
3 needs_profile 3 needs_profile
4 4
5 protect 'edit_profile_design', :profile 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 def available_blocks 16 def available_blocks
8 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] 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,9 +945,9 @@ module ApplicationHelper
945 # from Article model for an ArticleBlock. 945 # from Article model for an ArticleBlock.
946 def reference_to_article(text, article, anchor=nil) 946 def reference_to_article(text, article, anchor=nil)
947 if article.profile.domains.empty? 947 if article.profile.domains.empty?
948 - href = "/#{article.url[:profile]}/" 948 + href = "#{Noosfero.root}/#{article.url[:profile]}/"
949 else 949 else
950 - href = "http://#{article.profile.domains.first.name}/" 950 + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
951 end 951 end
952 href += article.url[:page].join('/') 952 href += article.url[:page].join('/')
953 href += '#' + anchor if anchor 953 href += '#' + anchor if anchor
app/helpers/article_helper.rb
@@ -77,12 +77,59 @@ module ArticleHelper @@ -77,12 +77,59 @@ module ArticleHelper
77 content_tag('div', 77 content_tag('div',
78 radio_button(:article, :published, false) + 78 radio_button(:article, :published, false) +
79 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") 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 end 133 end
87 134
88 def prepare_to_token_input(array) 135 def prepare_to_token_input(array)
app/helpers/boxes_helper.rb
@@ -170,49 +170,54 @@ module BoxesHelper @@ -170,49 +170,54 @@ module BoxesHelper
170 else 170 else
171 "before-block-#{block.id}" 171 "before-block-#{block.id}"
172 end 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 end 178 end
176 179
177 # makes the given block draggable so it can be moved away. 180 # makes the given block draggable so it can be moved away.
178 def block_handle(block) 181 def block_handle(block)
179 - draggable_element("block-#{block.id}", :revert => true) 182 + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
180 end 183 end
181 184
182 def block_edit_buttons(block) 185 def block_edit_buttons(block)
183 buttons = [] 186 buttons = []
184 nowhere = 'javascript: return false;' 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 end 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 end 221 end
217 222
218 if block.respond_to?(:help) 223 if block.respond_to?(:help)
@@ -248,5 +253,7 @@ module BoxesHelper @@ -248,5 +253,7 @@ module BoxesHelper
248 classes 253 classes
249 end 254 end
250 255
251 - 256 + def modifiable?(block)
  257 + return !block.fixed || environment.admins.include?(user)
  258 + end
252 end 259 end
app/helpers/content_viewer_helper.rb
@@ -45,7 +45,7 @@ module ContentViewerHelper @@ -45,7 +45,7 @@ module ContentViewerHelper
45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } 45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } }
46 end 46 end
47 content_tag(:div, link_to(_('Translations'), '#', 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 :class => 'article-translations-menu simplemenu-trigger up'), 49 :class => 'article-translations-menu simplemenu-trigger up'),
50 :class => 'article-translations') 50 :class => 'article-translations')
51 end 51 end
app/helpers/layout_helper.rb
@@ -2,6 +2,7 @@ module LayoutHelper @@ -2,6 +2,7 @@ module LayoutHelper
2 2
3 def body_classes 3 def body_classes
4 # Identify the current controller and action for the CSS: 4 # Identify the current controller and action for the CSS:
  5 + (logged_in? ? " logged-in" : "") +
5 " controller-#{controller.controller_name}" + 6 " controller-#{controller.controller_name}" +
6 " action-#{controller.controller_name}-#{controller.action_name}" + 7 " action-#{controller.controller_name}-#{controller.action_name}" +
7 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" + 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,6 +21,12 @@ module SearchHelper
21 'more_comments' => _('More comments') 21 'more_comments' => _('More comments')
22 } 22 }
23 23
  24 + COMMON_PROFILE_LIST_BLOCK = [
  25 + :enterprises,
  26 + :people,
  27 + :communities
  28 + ]
  29 +
24 # FIXME remove it after search_controler refactored 30 # FIXME remove it after search_controler refactored
25 include EventsHelper 31 include EventsHelper
26 32
@@ -94,7 +100,7 @@ module SearchHelper @@ -94,7 +100,7 @@ module SearchHelper
94 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil 100 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil
95 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil 101 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil
96 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil 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 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, 104 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe,
99 :class => 'search-customize-options' 105 :class => 'search-customize-options'
100 ) 106 )
app/models/article.rb
@@ -2,7 +2,14 @@ require &#39;hpricot&#39; @@ -2,7 +2,14 @@ require &#39;hpricot&#39;
2 2
3 class Article < ActiveRecord::Base 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 acts_as_having_image 14 acts_as_having_image
8 15
@@ -333,7 +340,7 @@ class Article &lt; ActiveRecord::Base @@ -333,7 +340,7 @@ class Article &lt; ActiveRecord::Base
333 def belongs_to_blog? 340 def belongs_to_blog?
334 self.parent and self.parent.blog? 341 self.parent and self.parent.blog?
335 end 342 end
336 - 343 +
337 def belongs_to_forum? 344 def belongs_to_forum?
338 self.parent and self.parent.forum? 345 self.parent and self.parent.forum?
339 end 346 end
@@ -445,6 +452,7 @@ class Article &lt; ActiveRecord::Base @@ -445,6 +452,7 @@ class Article &lt; ActiveRecord::Base
445 if self.parent && !self.parent.published? 452 if self.parent && !self.parent.published?
446 return false 453 return false
447 end 454 end
  455 +
448 true 456 true
449 else 457 else
450 false 458 false
@@ -476,14 +484,17 @@ class Article &lt; ActiveRecord::Base @@ -476,14 +484,17 @@ class Article &lt; ActiveRecord::Base
476 {:conditions => [" articles.published = ? OR 484 {:conditions => [" articles.published = ? OR
477 articles.last_changed_by_id = ? OR 485 articles.last_changed_by_id = ? OR
478 articles.profile_id = ? OR 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 end 490 end
482 491
  492 +
483 def display_unpublished_article_to?(user) 493 def display_unpublished_article_to?(user)
484 user == author || allow_view_private_content?(user) || user == profile || 494 user == author || allow_view_private_content?(user) || user == profile ||
485 user.is_admin?(profile.environment) || user.is_admin?(profile) || 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 end 498 end
488 499
489 def display_to?(user = nil) 500 def display_to?(user = nil)
app/models/block.rb
1 class Block < ActiveRecord::Base 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 # to be able to generate HTML 5 # to be able to generate HTML
6 include ActionView::Helpers::UrlHelper 6 include ActionView::Helpers::UrlHelper
@@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base @@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base
64 end 64 end
65 65
66 def display_to_user?(user) 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 end 68 end
69 69
70 def display_always(context) 70 def display_always(context)
@@ -110,6 +110,9 @@ class Block &lt; ActiveRecord::Base @@ -110,6 +110,9 @@ class Block &lt; ActiveRecord::Base
110 # * <tt>'all'</tt>: the block is always displayed 110 # * <tt>'all'</tt>: the block is always displayed
111 settings_items :language, :type => :string, :default => 'all' 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 # returns the description of the block, used when the user sees a list of 116 # returns the description of the block, used when the user sees a list of
114 # blocks to choose one to include in the design. 117 # blocks to choose one to include in the design.
115 # 118 #
@@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base @@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base
221 'all' => _('All users'), 224 'all' => _('All users'),
222 'logged' => _('Logged'), 225 'logged' => _('Logged'),
223 'not_logged' => _('Not logged'), 226 'not_logged' => _('Not logged'),
  227 + 'followers' => owner.organization? ? _('Members') : _('Friends')
224 } 228 }
225 end 229 end
226 230
app/models/blog.rb
@@ -53,7 +53,7 @@ class Blog &lt; Folder @@ -53,7 +53,7 @@ class Blog &lt; Folder
53 def prepare_external_feed 53 def prepare_external_feed
54 unless self.external_feed_data.nil? 54 unless self.external_feed_data.nil?
55 if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i 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 else 57 else
58 self.build_external_feed(self.external_feed_data, :without_protection => true) 58 self.build_external_feed(self.external_feed_data, :without_protection => true)
59 end 59 end
app/models/environment.rb
@@ -283,6 +283,7 @@ class Environment &lt; ActiveRecord::Base @@ -283,6 +283,7 @@ class Environment &lt; ActiveRecord::Base
283 www.flickr.com 283 www.flickr.com
284 www.gmodules.com 284 www.gmodules.com
285 www.youtube.com 285 www.youtube.com
  286 + openstreetmap.org
286 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} 287 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"}
287 288
288 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names 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,7 +10,7 @@ class ExternalFeed &lt; ActiveRecord::Base
10 { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] } 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 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?
app/models/invitation.rb
@@ -65,18 +65,16 @@ class Invitation &lt; Task @@ -65,18 +65,16 @@ class Invitation &lt; Task
65 65
66 task_args = if user.nil? 66 task_args = if user.nil?
67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} 67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message}
68 - elsif !user.person.is_a_friend?(person) 68 + else
69 {:person => person, :target => user.person} 69 {:person => person, :target => user.person}
70 end 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 end 78 end
81 end 79 end
82 end 80 end
app/models/person.rb
@@ -80,6 +80,10 @@ roles] } @@ -80,6 +80,10 @@ roles] }
80 80
81 belongs_to :user, :dependent => :delete 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 def can_control_scrap?(scrap) 87 def can_control_scrap?(scrap)
84 begin 88 begin
85 !self.scraps(scrap).nil? 89 !self.scraps(scrap).nil?
app/models/product.rb
@@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base @@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base
11 11
12 SEARCH_DISPLAYS = %w[map full] 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 def self.default_search_display 16 def self.default_search_display
17 'full' 17 'full'
app/views/box_organizer/edit.html.erb
@@ -5,6 +5,12 @@ @@ -5,6 +5,12 @@
5 5
6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> 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 <%= render :partial => partial_for_class(@block.class) %> 14 <%= render :partial => partial_for_class(@block.class) %>
9 15
10 <div class="display"> 16 <div class="display">
app/views/cms/upload_files.html.erb
@@ -20,5 +20,10 @@ @@ -20,5 +20,10 @@
20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5> 20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5>
21 21
22 <%= form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %> 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 <%= render :partial => 'upload_file_form', :locals => { :size => '45'} %> 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,7 +2,7 @@
2 <%= _('Content management') %> 2 <%= _('Content management') %>
3 </h1> 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 <div class="cms-homepage"> 6 <div class="cms-homepage">
7 <%= _('Profile homepage:') %> 7 <%= _('Profile homepage:') %>
8 <% if profile.home_page %> 8 <% if profile.home_page %>
@@ -69,7 +69,7 @@ @@ -69,7 +69,7 @@
69 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> 69 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %>
70 <%= button_without_text :eyes, _('Public view'), article.view_url %> 70 <%= button_without_text :eyes, _('Public view'), article.view_url %>
71 <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> 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 <% if profile.home_page != article %> 73 <% if profile.home_page != article %>
74 <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> 74 <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
75 <% else %> 75 <% else %>
app/views/events/events.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <div id='agenda-toolbar'> 3 <div id='agenda-toolbar'>
4 <%= button :back, _('Back to %s') % profile.name, profile.url %> 4 <%= button :back, _('Back to %s') % profile.name, profile.url %>
5 <% if user && user.has_permission?('post_content', profile) %> 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 <% end %> 7 <% end %>
8 </div> 8 </div>
9 9
app/views/manage_products/_edit_info.html.erb
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 <%= button_to_function( 47 <%= button_to_function(
48 :add, 48 :add,
49 _('Add new qualifier'), 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 <%= hidden_field_tag "product[qualifiers_list][nil]" %> 52 <%= hidden_field_tag "product[qualifiers_list][nil]" %>
53 <% end %> 53 <% end %>
app/views/search/_display_results.html.erb
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 14
15 <% display = display_filter(name, params[:display]) %> 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 <ul> 18 <ul>
19 <% search[:results].each do |hit| %> 19 <% search[:results].each do |hit| %>
20 <% partial = partial_for_class(hit.class, display) %> 20 <% partial = partial_for_class(hit.class, display) %>
db/migrate/20150113131617_add_show_to_followers_for_article.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -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
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 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 create_table "abuse_reports", :force => true do |t| 16 create_table "abuse_reports", :force => true do |t|
17 t.integer "reporter_id" 17 t.integer "reporter_id"
@@ -149,6 +149,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do @@ -149,6 +149,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do
149 t.integer "spam_comments_count", :default => 0 149 t.integer "spam_comments_count", :default => 0
150 t.integer "author_id" 150 t.integer "author_id"
151 t.integer "created_by_id" 151 t.integer "created_by_id"
  152 + t.boolean "show_to_followers", :default => false
152 end 153 end
153 154
154 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count" 155 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
features/edit_article.feature
@@ -47,6 +47,28 @@ Feature: edit article @@ -47,6 +47,28 @@ Feature: edit article
47 Then I should see "Access denied" 47 Then I should see "Access denied"
48 48
49 @selenium 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 Scenario: show exception users field when you choose the private option 72 Scenario: show exception users field when you choose the private option
51 Given the following communities 73 Given the following communities
52 | name | identifier | owner | 74 | name | identifier | owner |
lib/noosfero/plugin.rb
@@ -417,6 +417,12 @@ class Noosfero::Plugin @@ -417,6 +417,12 @@ class Noosfero::Plugin
417 nil 417 nil
418 end 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 # -> Adds fields to the signup form 426 # -> Adds fields to the signup form
421 # returns = proc that creates html code 427 # returns = proc that creates html code
422 def signup_extra_contents 428 def signup_extra_contents
plugins/work_assignment/controllers/work_assignment_plugin_myprofile_controller.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -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 @@ @@ -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 \ No newline at end of file 21 \ No newline at end of file
plugins/work_assignment/lib/ext/folder.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -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,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,8 +9,8 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin
9 end 9 end
10 10
11 def self.can_download_submission?(user, submission) 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 end 14 end
15 15
16 def self.is_submission?(content) 16 def self.is_submission?(content)
@@ -37,7 +37,7 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin @@ -37,7 +37,7 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin
37 37
38 def content_viewer_controller_filters 38 def content_viewer_controller_filters
39 block = proc do 39 block = proc do
40 - path = params[:page] 40 + path = get_path(params[:page], params[:format])
41 content = profile.articles.find_by_path(path) 41 content = profile.articles.find_by_path(path)
42 42
43 if WorkAssignmentPlugin.is_submission?(content) && !WorkAssignmentPlugin.can_download_submission?(user, content) 43 if WorkAssignmentPlugin.is_submission?(content) && !WorkAssignmentPlugin.can_download_submission?(user, content)
@@ -51,4 +51,34 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin @@ -51,4 +51,34 @@ class WorkAssignmentPlugin &lt; Noosfero::Plugin
51 :block => block } 51 :block => block }
52 end 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 end 84 end
plugins/work_assignment/lib/work_assignment_plugin/email_contact.rb 0 → 100644
@@ -0,0 +1,64 @@ @@ -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 module WorkAssignmentPlugin::Helper 1 module WorkAssignmentPlugin::Helper
  2 + include CmsHelper
  3 +
2 def display_submissions(work_assignment, user) 4 def display_submissions(work_assignment, user)
3 return if work_assignment.submissions.empty? 5 return if work_assignment.submissions.empty?
4 content_tag('table', 6 content_tag('table',
@@ -6,6 +8,7 @@ module WorkAssignmentPlugin::Helper @@ -6,6 +8,7 @@ module WorkAssignmentPlugin::Helper
6 content_tag('th', c_('Author'), :style => 'width: 50%') + 8 content_tag('th', c_('Author'), :style => 'width: 50%') +
7 content_tag('th', _('Submission date')) + 9 content_tag('th', _('Submission date')) +
8 content_tag('th', _('Versions'), :style => 'text-align: center') + 10 content_tag('th', _('Versions'), :style => 'text-align: center') +
  11 + content_tag('th', '') +
9 content_tag('th', '') 12 content_tag('th', '')
10 ).html_safe + 13 ).html_safe +
11 work_assignment.children.map {|author_folder| display_author_folder(author_folder, user)}.join("\n").html_safe 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,7 +21,8 @@ module WorkAssignmentPlugin::Helper
18 content_tag('td', link_to_last_submission(author_folder, user)) + 21 content_tag('td', link_to_last_submission(author_folder, user)) +
19 content_tag('td', time_format(author_folder.children.last.created_at)) + 22 content_tag('td', time_format(author_folder.children.last.created_at)) +
20 content_tag('td', author_folder.children.count, :style => 'text-align: center') + 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 ).html_safe + 26 ).html_safe +
23 author_folder.children.map {|submission| display_submission(submission, user)}.join("\n").html_safe 27 author_folder.children.map {|submission| display_submission(submission, user)}.join("\n").html_safe
24 end 28 end
@@ -26,7 +30,13 @@ module WorkAssignmentPlugin::Helper @@ -26,7 +30,13 @@ module WorkAssignmentPlugin::Helper
26 def display_submission(submission, user) 30 def display_submission(submission, user)
27 content_tag('tr', 31 content_tag('tr',
28 content_tag('td', link_to_submission(submission, user)) + 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 :class => "submission-from-#{submission.parent.id}", 40 :class => "submission-from-#{submission.parent.id}",
31 :style => 'display: none' 41 :style => 'display: none'
32 ) 42 )
@@ -40,7 +50,6 @@ module WorkAssignmentPlugin::Helper @@ -40,7 +50,6 @@ module WorkAssignmentPlugin::Helper
40 end 50 end
41 end 51 end
42 52
43 -  
44 def link_to_last_submission(author_folder, user) 53 def link_to_last_submission(author_folder, user)
45 if WorkAssignmentPlugin.can_download_submission?(user, author_folder.children.last) 54 if WorkAssignmentPlugin.can_download_submission?(user, author_folder.children.last)
46 link_to(author_folder.name, author_folder.children.last.url) 55 link_to(author_folder.name, author_folder.children.last.url)
@@ -48,6 +57,7 @@ module WorkAssignmentPlugin::Helper @@ -48,6 +57,7 @@ module WorkAssignmentPlugin::Helper
48 author_folder.name 57 author_folder.name
49 end 58 end
50 end 59 end
  60 +
51 # FIXME Copied from custom-froms. Consider passing it to core... 61 # FIXME Copied from custom-froms. Consider passing it to core...
52 def time_format(time) 62 def time_format(time)
53 minutes = (time.min == 0) ? '' : ':%M' 63 minutes = (time.min == 0) ? '' : ':%M'
@@ -56,4 +66,28 @@ module WorkAssignmentPlugin::Helper @@ -56,4 +66,28 @@ module WorkAssignmentPlugin::Helper
56 time.strftime("%Y-%m-%d#{hour+minutes+h}") 66 time.strftime("%Y-%m-%d#{hour+minutes+h}")
57 end 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 end 93 end
plugins/work_assignment/lib/work_assignment_plugin/work_assignment.rb
1 class WorkAssignmentPlugin::WorkAssignment < Folder 1 class WorkAssignmentPlugin::WorkAssignment < Folder
2 2
3 settings_items :publish_submissions, :type => :boolean, :default => false 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 attr_accessible :publish_submissions 7 attr_accessible :publish_submissions
6 - 8 + attr_accessible :default_email
  9 + attr_accessible :allow_visibility_edition
  10 +
7 def self.icon_name(article = nil) 11 def self.icon_name(article = nil)
8 'work-assignment' 12 'work-assignment'
9 end 13 end
@@ -29,13 +33,22 @@ class WorkAssignmentPlugin::WorkAssignment &lt; Folder @@ -29,13 +33,22 @@ class WorkAssignmentPlugin::WorkAssignment &lt; Folder
29 end 33 end
30 34
31 def to_html(options = {}) 35 def to_html(options = {})
32 - proc do 36 + lambda do
33 render :file => 'content_viewer/work_assignment.html.erb' 37 render :file => 'content_viewer/work_assignment.html.erb'
34 end 38 end
35 end 39 end
36 40
37 def find_or_create_author_folder(author) 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 end 52 end
40 53
41 def submissions 54 def submissions
@@ -45,6 +58,5 @@ class WorkAssignmentPlugin::WorkAssignment &lt; Folder @@ -45,6 +58,5 @@ class WorkAssignmentPlugin::WorkAssignment &lt; Folder
45 def cache_key_with_person(params = {}, user = nil, language = 'en') 58 def cache_key_with_person(params = {}, user = nil, language = 'en')
46 cache_key_without_person + (user && profile.members.include?(user) ? "-#{user.identifier}" : '') 59 cache_key_without_person + (user && profile.members.include?(user) ? "-#{user.identifier}" : '')
47 end 60 end
48 - alias_method_chain :cache_key, :person  
49 - 61 + alias_method_chain :cache_key, :person
50 end 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 require 'cms_controller' 2 require 'cms_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
@@ -12,33 +12,67 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -12,33 +12,67 @@ class CmsControllerTest &lt; ActionController::TestCase
12 @response = ActionController::TestResponse.new 12 @response = ActionController::TestResponse.new
13 @person = create_user('test_user').person 13 @person = create_user('test_user').person
14 login_as :test_user 14 login_as :test_user
  15 + e = Environment.default
  16 + e.enabled_plugins = ['WorkAssignmentPlugin']
  17 + e.save!
  18 + @organization = fast_create(Organization) #
15 end 19 end
16 20
17 - attr_accessor :person  
18 -  
19 should 'not allow non-members to upload submissions on work_assignment' do 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 assert_response :forbidden 24 assert_response :forbidden
25 assert_template 'access_denied' 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 assert_response :success 33 assert_response :success
31 end 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 should 'upload submission and automatically move it to the author folder' do 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 submission = UploadedFile.last 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 end 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 end 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 require 'content_viewer_controller' 2 require 'content_viewer_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
@@ -15,6 +15,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -15,6 +15,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
15 @organization = fast_create(Organization) 15 @organization = fast_create(Organization)
16 @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => @organization) 16 @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => @organization)
17 @person = create_user('test_user').person 17 @person = create_user('test_user').person
  18 + @organization.add_member(@person)
18 @environment = @organization.environment 19 @environment = @organization.environment
19 @environment.enable_plugin(WorkAssignmentPlugin) 20 @environment.enable_plugin(WorkAssignmentPlugin)
20 @environment.save! 21 @environment.save!
@@ -23,19 +24,17 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -23,19 +24,17 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
23 attr_reader :organization, :person, :profile, :work_assignment 24 attr_reader :organization, :person, :profile, :work_assignment
24 25
25 should 'can download work_assignment' do 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 submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder) 28 submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder)
30 WorkAssignmentPlugin.stubs(:can_download_submission?).returns(false) 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 assert_response :forbidden 32 assert_response :forbidden
34 assert_template 'access_denied' 33 assert_template 'access_denied'
35 34
36 WorkAssignmentPlugin.stubs(:can_download_submission?).returns(true) 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 assert_response :success 38 assert_response :success
40 end 39 end
41 40
plugins/work_assignment/test/functional/work_assignment_plugin_myprofile_controller_test.rb 0 → 100644
@@ -0,0 +1,191 @@ @@ -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 class WorkAssignmentTest < ActiveSupport::TestCase 3 class WorkAssignmentTest < ActiveSupport::TestCase
4 should 'find or create sub-folder based on author identifier' do 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 class WorkAssignmentPluginTest < ActiveSupport::TestCase 3 class WorkAssignmentPluginTest < ActiveSupport::TestCase
4 should 'verify if a content is a work_assignment submission' do 4 should 'verify if a content is a work_assignment submission' do
5 organization = fast_create(Organization) 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 assert !WorkAssignmentPlugin.is_submission?(content) 18 assert !WorkAssignmentPlugin.is_submission?(content)
8 19
9 work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) 20 work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization)
@@ -22,7 +33,9 @@ class WorkAssignmentPluginTest &lt; ActiveSupport::TestCase @@ -22,7 +33,9 @@ class WorkAssignmentPluginTest &lt; ActiveSupport::TestCase
22 work_assignment = submission.parent.parent 33 work_assignment = submission.parent.parent
23 work_assignment.publish_submissions = true 34 work_assignment.publish_submissions = true
24 work_assignment.save! 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 end 39 end
27 40
28 should 'be able to download submission if the user is author of it' do 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,12 +58,21 @@ class WorkAssignmentPluginTest &lt; ActiveSupport::TestCase
45 58
46 private 59 private
47 60
48 - def create_submission(author=nil) 61 + def create_submission(author=nil, work_assignment=nil)
49 author ||= fast_create(Person) 62 author ||= fast_create(Person)
50 organization = fast_create(Organization) 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 author_folder = work_assignment.find_or_create_author_folder(author) 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 end 77 end
56 end 78 end
plugins/work_assignment/views/cms/_notify_text_field.html.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -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 <%= render :partial => 'folder', :locals => {:f => f} %> 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 @@ @@ -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,7 +136,7 @@ jQuery(function($) {
136 if (data.length && data.length > 0) { 136 if (data.length && data.length > 0) {
137 $('#media-search-results').slideDown(); 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 return false; 141 return false;
142 }); 142 });
@@ -144,20 +144,20 @@ jQuery(function($) { @@ -144,20 +144,20 @@ jQuery(function($) {
144 $('#media-upload-form form').ajaxForm({ 144 $('#media-upload-form form').ajaxForm({
145 resetForm: true, 145 resetForm: true,
146 beforeSubmit: 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 success: 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 $('#media-upload-more-files').click(function() { 163 $('#media-upload-more-files').click(function() {
@@ -166,19 +166,45 @@ jQuery(function($) { @@ -166,19 +166,45 @@ jQuery(function($) {
166 return false; 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 function show_hide_token_input() { 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 if( $("#token-input-search-article-privacy-exceptions").length == 1 ) { 196 if( $("#token-input-search-article-privacy-exceptions").length == 1 ) {
  197 + show_hide_privacy_options();
177 show_hide_token_input(); 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 require 'account_controller' 2 require 'account_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'admin_controller' 2 require 'admin_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'admin_panel_controller' 2 require 'admin_panel_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
test/functional/application_controller_test.rb
1 # encoding: UTF-8 1 # encoding: UTF-8
2 -require File.dirname(__FILE__) + '/../test_helper' 2 +require_relative "../test_helper"
3 require 'test_controller' 3 require 'test_controller'
4 4
5 # Re-raise errors caught by the controller. 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 require 'catalog_controller' 2 require 'catalog_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'categories_controller' 2 require 'categories_controller'
3 3
4 # Re-raise errors caught by the controller. 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 class ChatControllerTest < ActionController::TestCase 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 require 'cms_controller' 2 require 'cms_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
@@ -101,12 +101,26 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -101,12 +101,26 @@ class CmsControllerTest &lt; ActionController::TestCase
101 assert_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"} 101 assert_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"}
102 end 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 should 'not display the profile homepage if cannot change homepage' do 111 should 'not display the profile homepage if cannot change homepage' do
105 env = Environment.default; env.enable('cant_change_homepage') 112 env = Environment.default; env.enable('cant_change_homepage')
106 get :index, :profile => profile.identifier 113 get :index, :profile => profile.identifier
107 assert_no_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"} 114 assert_no_tag :tag => 'div', :content => /Profile homepage/, :attributes => { :class => "cms-homepage"}
108 end 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 should 'be able to set home page' do 124 should 'be able to set home page' do
111 a = profile.articles.build(:name => 'my new home page') 125 a = profile.articles.build(:name => 'my new home page')
112 a.save! 126 a.save!
test/functional/comment_controller_test.rb
1 -require File.dirname(__FILE__) + '/../test_helper' 1 +require_relative "../test_helper"
2 require 'comment_controller' 2 require 'comment_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
test/functional/contact_controller_test.rb
1 # encoding: UTF-8 1 # encoding: UTF-8
2 -require File.dirname(__FILE__) + '/../test_helper' 2 +require_relative "../test_helper"
3 require 'contact_controller' 3 require 'contact_controller'
4 4
5 # Re-raise errors caught by the controller. 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 require 'content_viewer_controller' 2 require 'content_viewer_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
@@ -661,8 +661,8 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -661,8 +661,8 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
661 get :view_page, :profile => owner.identifier, :page => folder.path 661 get :view_page, :profile => owner.identifier, :page => folder.path
662 assert_response :success 662 assert_response :success
663 assert_select '.image-gallery-item', 0 663 assert_select '.image-gallery-item', 0
664 - end  
665 - 664 + end
  665 +
666 666
667 should 'display default image in the slideshow if thumbnails were not processed' do 667 should 'display default image in the slideshow if thumbnails were not processed' do
668 @controller.stubs(:per_page).returns(1) 668 @controller.stubs(:per_page).returns(1)
@@ -1296,14 +1296,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1296,14 +1296,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1296 def comment_form_extra_contents(args) 1296 def comment_form_extra_contents(args)
1297 proc { 1297 proc {
1298 hidden_field_tag('comment[some_field_id]', 1) 1298 hidden_field_tag('comment[some_field_id]', 1)
1299 - } 1299 + }
1300 end 1300 end
1301 end 1301 end
1302 class Plugin2 < Noosfero::Plugin 1302 class Plugin2 < Noosfero::Plugin
1303 def comment_form_extra_contents(args) 1303 def comment_form_extra_contents(args)
1304 proc { 1304 proc {
1305 hidden_field_tag('comment[another_field_id]', 1) 1305 hidden_field_tag('comment[another_field_id]', 1)
1306 - } 1306 + }
1307 end 1307 end
1308 end 1308 end
1309 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name]) 1309 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
@@ -1373,20 +1373,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1373,20 +1373,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1373 get :view_page, :profile => profile.identifier, :page => [blog.path] 1373 get :view_page, :profile => profile.identifier, :page => [blog.path]
1374 assert_tag :tag => 'strong', :content => /bold/ 1374 assert_tag :tag => 'strong', :content => /bold/
1375 end 1375 end
1376 - 1376 +
1377 should 'add extra content on article header from plugins' do 1377 should 'add extra content on article header from plugins' do
1378 class Plugin1 < Noosfero::Plugin 1378 class Plugin1 < Noosfero::Plugin
1379 def article_header_extra_contents(args) 1379 def article_header_extra_contents(args)
1380 proc { 1380 proc {
1381 content_tag('div', '', :class => 'plugin1') 1381 content_tag('div', '', :class => 'plugin1')
1382 - } 1382 + }
1383 end 1383 end
1384 end 1384 end
1385 class Plugin2 < Noosfero::Plugin 1385 class Plugin2 < Noosfero::Plugin
1386 def article_header_extra_contents(args) 1386 def article_header_extra_contents(args)
1387 proc { 1387 proc {
1388 content_tag('div', '', :class => 'plugin2') 1388 content_tag('div', '', :class => 'plugin2')
1389 - } 1389 + }
1390 end 1390 end
1391 end 1391 end
1392 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name]) 1392 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
@@ -1447,4 +1447,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1447,4 +1447,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1447 assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ } 1447 assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ }
1448 end 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 end 1481 end
test/functional/doc_controller_test.rb
1 -require File.dirname(__FILE__) + '/../test_helper' 1 +require_relative "../test_helper"
2 2
3 class DocControllerTest < ActionController::TestCase 3 class DocControllerTest < ActionController::TestCase
4 4
test/functional/edit_template_controller_test.rb
1 # FIXME: this tests must me moved into design plugin 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 require 'edit_template_controller' 4 require 'edit_template_controller'
5 5
6 # Re-raise errors caught by the controller. 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 class EmbedControllerTest < ActionController::TestCase 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 require 'enterprise_registration_controller' 2 require 'enterprise_registration_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'enterprise_validation_controller' 2 require 'enterprise_validation_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'environment_design_controller' 2 require 'environment_design_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'environment_role_manager_controller' 2 require 'environment_role_manager_controller'
3 3
4 # Re-raise errors caught by the controller. 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 class EnvironmentThemesController; def rescue_action(e) raise e end; end 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 class EventsControllerTest < ActionController::TestCase 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 require 'favorite_enterprises_controller' 2 require 'favorite_enterprises_controller'
3 3
4 class FavoriteEnterprisesController; def rescue_action(e) raise e end; end 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 require 'features_controller' 2 require 'features_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'friends_controller' 2 require 'friends_controller'
3 3
4 class FriendsController; def rescue_action(e) raise e end; end 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 require 'home_controller' 2 require 'home_controller'
3 3
4 # Re-raise errors caught by the controller. 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 class InviteControllerTest < ActionController::TestCase 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 require 'licenses_controller' 2 require 'licenses_controller'
3 3
4 # Re-raise errors caught by the controller. 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 class MailconfControllerTest < ActionController::TestCase 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 require 'manage_products_controller' 2 require 'manage_products_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'map_balloon_controller' 2 require 'map_balloon_controller'
3 3
4 4
test/functional/maps_controller_test.rb
1 # encoding: UTF-8 1 # encoding: UTF-8
2 -require File.dirname(__FILE__) + '/../test_helper' 2 +require_relative "../test_helper"
3 require 'maps_controller' 3 require 'maps_controller'
4 4
5 # Re-raise errors caught by the controller. 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 require 'memberships_controller' 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 require 'my_profile_controller' 2 require 'my_profile_controller'
3 3
4 # Re-raise errors caught by the controller. 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 class PluginAdminController 3 class PluginAdminController
4 def index 4 def index
test/functional/plugins_controller_test.rb
1 -require File.dirname(__FILE__) + '/../test_helper' 1 +require_relative "../test_helper"
2 require 'plugins_controller' 2 require 'plugins_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'profile_controller' 2 require 'profile_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'profile_design_controller' 2 require 'profile_design_controller'
3 3
4 class ProfileDesignController; def rescue_action(e) raise e end; end 4 class ProfileDesignController; def rescue_action(e) raise e end; end
@@ -737,4 +737,22 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -737,4 +737,22 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
737 end 737 end
738 end 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 end 758 end
test/functional/profile_editor_controller_test.rb
1 -require File.dirname(__FILE__) + '/../test_helper' 1 +require_relative "../test_helper"
2 require 'profile_editor_controller' 2 require 'profile_editor_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'profile_members_controller' 2 require 'profile_members_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'profile_search_controller' 2 require 'profile_search_controller'
3 3
4 # Re-raise errors caught by the controller. 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 # require 'profile_themes_controller' 2 # require 'profile_themes_controller'
3 3
4 class ProfileThemesController; def rescue_action(e) raise e end; end 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 require 'public_controller' 2 require 'public_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'region_validators_controller' 2 require 'region_validators_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'role_controller' 2 require 'role_controller'
3 3
4 # Re-raise errors caught by the controller. 4 # Re-raise errors caught by the controller.
test/functional/search_controller_test.rb
1 # encoding: UTF-8 1 # encoding: UTF-8
2 -require File.dirname(__FILE__) + '/../test_helper' 2 +require_relative "../test_helper"
3 require 'search_controller' 3 require 'search_controller'
4 4
5 # Re-raise errors caught by the controller. 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 class SpamControllerTest < ActionController::TestCase 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 require 'system_controller' 2 require 'system_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'tasks_controller' 2 require 'tasks_controller'
3 3
4 class TasksController; def rescue_action(e) raise e end; end 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 require 'templates_controller' 2 require 'templates_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'trusted_sites_controller' 2 require 'trusted_sites_controller'
3 3
4 # Re-raise errors caught by the controller. 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 require 'users_controller' 2 require 'users_controller'
3 3
4 # Re-raise errors caught by the controller. 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 class ApproveRejectEnterpriseTest < ActionController::IntegrationTest 3 class ApproveRejectEnterpriseTest < ActionController::IntegrationTest
4 all_fixtures 4 all_fixtures
test/integration/assets_menu_test.rb
1 -require "#{File.dirname(__FILE__)}/../test_helper" 1 +require_relative "../test_helper"
2 2
3 class AssetsMenuTest < ActionController::IntegrationTest 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 class AssigningValidatorOrganizationsToRegionsTest < ActionController::IntegrationTest 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 class BlocksTest < ActionController::IntegrationTest 3 class BlocksTest < ActionController::IntegrationTest
4 def blog_on_article_block_bootstrap 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 class CategoriesMenuTest < ActionController::IntegrationTest 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 class ControllerNamingTest < ActionController::IntegrationTest 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 class EditingPersonInfoTest < ActionController::IntegrationTest 3 class EditingPersonInfoTest < ActionController::IntegrationTest
4 4