Commit e5d9ef3a5249c2642ba63a6e0f1f647b0e80826c
Exists in
master
and in
22 other branches
Merge branch 'AI2852'
Showing
15 changed files
with
224 additions
and
79 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
| @@ -2,6 +2,8 @@ class CmsController < MyProfileController | @@ -2,6 +2,8 @@ class CmsController < MyProfileController | ||
| 2 | 2 | ||
| 3 | protect 'edit_profile', :profile, :only => [:set_home_page] | 3 | protect 'edit_profile', :profile, :only => [:set_home_page] |
| 4 | 4 | ||
| 5 | + include ArticleHelper | ||
| 6 | + | ||
| 5 | def self.protect_if(*args) | 7 | def self.protect_if(*args) |
| 6 | before_filter(*args) do |c| | 8 | before_filter(*args) do |c| |
| 7 | user, profile = c.send(:user), c.send(:profile) | 9 | user, profile = c.send(:user), c.send(:profile) |
| @@ -70,6 +72,13 @@ class CmsController < MyProfileController | @@ -70,6 +72,13 @@ class CmsController < MyProfileController | ||
| 70 | translations if @article.translatable? | 72 | translations if @article.translatable? |
| 71 | continue = params[:continue] | 73 | continue = params[:continue] |
| 72 | 74 | ||
| 75 | + @article.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i} unless params[:q].nil? | ||
| 76 | + | ||
| 77 | + @tokenized_children = prepare_to_token_input( | ||
| 78 | + profile.members.includes(:articles_with_access).find_all{ |m| | ||
| 79 | + m.articles_with_access.include?(@article) | ||
| 80 | + } | ||
| 81 | + ) | ||
| 73 | refuse_blocks | 82 | refuse_blocks |
| 74 | record_coming | 83 | record_coming |
| 75 | if request.post? | 84 | if request.post? |
| @@ -130,6 +139,8 @@ class CmsController < MyProfileController | @@ -130,6 +139,8 @@ class CmsController < MyProfileController | ||
| 130 | 139 | ||
| 131 | continue = params[:continue] | 140 | continue = params[:continue] |
| 132 | if request.post? | 141 | if request.post? |
| 142 | + @article.article_privacy_exceptions = params[:q].split(/,/).map{|n| environment.people.find n.to_i} unless params[:q].nil? | ||
| 143 | + | ||
| 133 | if @article.save | 144 | if @article.save |
| 134 | if continue | 145 | if continue |
| 135 | redirect_to :action => 'edit', :id => @article | 146 | redirect_to :action => 'edit', :id => @article |
| @@ -290,6 +301,12 @@ class CmsController < MyProfileController | @@ -290,6 +301,12 @@ class CmsController < MyProfileController | ||
| 290 | render :text => article_list_to_json(results), :content_type => 'application/json' | 301 | render :text => article_list_to_json(results), :content_type => 'application/json' |
| 291 | end | 302 | end |
| 292 | 303 | ||
| 304 | + def search_article_privacy_exceptions | ||
| 305 | + arg = params[:q].downcase | ||
| 306 | + result = profile.members.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"]) | ||
| 307 | + render :text => prepare_to_token_input(result).to_json | ||
| 308 | + end | ||
| 309 | + | ||
| 293 | def media_upload | 310 | def media_upload |
| 294 | files_uploaded = [] | 311 | files_uploaded = [] |
| 295 | parent = check_parent(params[:parent_id]) | 312 | parent = check_parent(params[:parent_id]) |
app/helpers/application_helper.rb
| @@ -40,6 +40,8 @@ module ApplicationHelper | @@ -40,6 +40,8 @@ module ApplicationHelper | ||
| 40 | 40 | ||
| 41 | include Noosfero::Gravatar | 41 | include Noosfero::Gravatar |
| 42 | 42 | ||
| 43 | + include TokenHelper | ||
| 44 | + | ||
| 43 | def locale | 45 | def locale |
| 44 | (@page && !@page.language.blank?) ? @page.language : FastGettext.locale | 46 | (@page && !@page.language.blank?) ? @page.language : FastGettext.locale |
| 45 | end | 47 | end |
| @@ -1300,10 +1302,6 @@ module ApplicationHelper | @@ -1300,10 +1302,6 @@ module ApplicationHelper | ||
| 1300 | content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs') | 1302 | content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs') |
| 1301 | end | 1303 | end |
| 1302 | 1304 | ||
| 1303 | - def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...')) | ||
| 1304 | - "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'" | ||
| 1305 | - end | ||
| 1306 | - | ||
| 1307 | def delete_article_message(article) | 1305 | def delete_article_message(article) |
| 1308 | if article.folder? | 1306 | if article.folder? |
| 1309 | _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") | 1307 | _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") |
| @@ -1344,50 +1342,6 @@ module ApplicationHelper | @@ -1344,50 +1342,6 @@ module ApplicationHelper | ||
| 1344 | ) | 1342 | ) |
| 1345 | end | 1343 | end |
| 1346 | 1344 | ||
| 1347 | - def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {}) | ||
| 1348 | - options[:min_chars] ||= 3 | ||
| 1349 | - options[:hint_text] ||= _("Type in a search term") | ||
| 1350 | - options[:no_results_text] ||= _("No results") | ||
| 1351 | - options[:searching_text] ||= _("Searching...") | ||
| 1352 | - options[:search_delay] ||= 1000 | ||
| 1353 | - options[:prevent_duplicates] ||= true | ||
| 1354 | - options[:backspace_delete_item] ||= false | ||
| 1355 | - options[:focus] ||= false | ||
| 1356 | - options[:avoid_enter] ||= true | ||
| 1357 | - options[:on_result] ||= 'null' | ||
| 1358 | - options[:on_add] ||= 'null' | ||
| 1359 | - options[:on_delete] ||= 'null' | ||
| 1360 | - options[:on_ready] ||= 'null' | ||
| 1361 | - | ||
| 1362 | - result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) | ||
| 1363 | - result += javascript_tag("jQuery('##{element_id}') | ||
| 1364 | - .tokenInput('#{url_for(search_action)}', { | ||
| 1365 | - minChars: #{options[:min_chars].to_json}, | ||
| 1366 | - prePopulate: #{options[:pre_populate].to_json}, | ||
| 1367 | - hintText: #{options[:hint_text].to_json}, | ||
| 1368 | - noResultsText: #{options[:no_results_text].to_json}, | ||
| 1369 | - searchingText: #{options[:searching_text].to_json}, | ||
| 1370 | - searchDelay: #{options[:serach_delay].to_json}, | ||
| 1371 | - preventDuplicates: #{options[:prevent_duplicates].to_json}, | ||
| 1372 | - backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, | ||
| 1373 | - queryParam: #{name.to_json}, | ||
| 1374 | - tokenLimit: #{options[:token_limit].to_json}, | ||
| 1375 | - onResult: #{options[:on_result]}, | ||
| 1376 | - onAdd: #{options[:on_add]}, | ||
| 1377 | - onDelete: #{options[:on_delete]}, | ||
| 1378 | - onReady: #{options[:on_ready]}, | ||
| 1379 | - }); | ||
| 1380 | - ") | ||
| 1381 | - result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus] | ||
| 1382 | - if options[:avoid_enter] | ||
| 1383 | - result += javascript_tag("jQuery('#token-input-#{element_id}') | ||
| 1384 | - .live('keydown', function(event){ | ||
| 1385 | - if(event.keyCode == '13') return false; | ||
| 1386 | - });") | ||
| 1387 | - end | ||
| 1388 | - result | ||
| 1389 | - end | ||
| 1390 | - | ||
| 1391 | def expirable_content_reference(content, action, text, url, options = {}) | 1345 | def expirable_content_reference(content, action, text, url, options = {}) |
| 1392 | reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first | 1346 | reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first |
| 1393 | options[:title] = reason | 1347 | options[:title] = reason |
app/helpers/article_helper.rb
| 1 | module ArticleHelper | 1 | module ArticleHelper |
| 2 | 2 | ||
| 3 | - def custom_options_for_article(article) | 3 | + include TokenHelper |
| 4 | + | ||
| 5 | + def custom_options_for_article(article, tokenized_children) | ||
| 4 | @article = article | 6 | @article = article |
| 5 | - content_tag('h4', _('Visibility')) + | ||
| 6 | - content_tag('div', | ||
| 7 | - content_tag('div', | ||
| 8 | - radio_button(:article, :published, true) + | ||
| 9 | - content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') | ||
| 10 | - ) + | ||
| 11 | - content_tag('div', | ||
| 12 | - radio_button(:article, :published, false) + | ||
| 13 | - content_tag('label', _('Private'), :for => 'article_published_false') | ||
| 14 | - ) | ||
| 15 | - ) + | 7 | + |
| 8 | + visibility_options(@article, tokenized_children) + | ||
| 16 | content_tag('h4', _('Options')) + | 9 | content_tag('h4', _('Options')) + |
| 17 | content_tag('div', | 10 | content_tag('div', |
| 18 | (article.profile.has_members? ? | 11 | (article.profile.has_members? ? |
| @@ -53,6 +46,28 @@ module ArticleHelper | @@ -53,6 +46,28 @@ module ArticleHelper | ||
| 53 | ) | 46 | ) |
| 54 | end | 47 | end |
| 55 | 48 | ||
| 49 | + def visibility_options(article, tokenized_children) | ||
| 50 | + content_tag('h4', _('Visibility')) + | ||
| 51 | + content_tag('div', | ||
| 52 | + content_tag('div', | ||
| 53 | + radio_button(:article, :published, true) + | ||
| 54 | + content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') | ||
| 55 | + ) + | ||
| 56 | + content_tag('div', | ||
| 57 | + radio_button(:article, :published, false) + | ||
| 58 | + content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") | ||
| 59 | + ) + | ||
| 60 | + (article.profile.community? ? content_tag('div', | ||
| 61 | + content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") + | ||
| 62 | + token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'}, | ||
| 63 | + {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) : | ||
| 64 | + '')) | ||
| 65 | + end | ||
| 66 | + | ||
| 67 | + def prepare_to_token_input(array) | ||
| 68 | + array.map { |object| {:id => object.id, :name => object.name} } | ||
| 69 | + end | ||
| 70 | + | ||
| 56 | def cms_label_for_new_children | 71 | def cms_label_for_new_children |
| 57 | _('New article') | 72 | _('New article') |
| 58 | end | 73 | end |
app/helpers/blog_helper.rb
| 1 | module BlogHelper | 1 | module BlogHelper |
| 2 | 2 | ||
| 3 | - def custom_options_for_article(article) | 3 | + include ArticleHelper |
| 4 | + | ||
| 5 | + def custom_options_for_article(article,tokenized_children) | ||
| 4 | @article = article | 6 | @article = article |
| 5 | hidden_field_tag('article[published]', 1) + | 7 | hidden_field_tag('article[published]', 1) + |
| 6 | - hidden_field_tag('article[accept_comments]', 0) | 8 | + hidden_field_tag('article[accept_comments]', 0) + |
| 9 | + visibility_options(article,tokenized_children) | ||
| 7 | end | 10 | end |
| 8 | 11 | ||
| 9 | def cms_label_for_new_children | 12 | def cms_label_for_new_children |
app/helpers/cms_helper.rb
| @@ -22,9 +22,9 @@ module CmsHelper | @@ -22,9 +22,9 @@ module CmsHelper | ||
| 22 | 22 | ||
| 23 | attr_reader :environment | 23 | attr_reader :environment |
| 24 | 24 | ||
| 25 | - def options_for_article(article) | 25 | + def options_for_article(article, tokenized_children=nil) |
| 26 | article_helper = helper_for_article(article) | 26 | article_helper = helper_for_article(article) |
| 27 | - article_helper.custom_options_for_article(article) | 27 | + article_helper.custom_options_for_article(article, tokenized_children) |
| 28 | end | 28 | end |
| 29 | 29 | ||
| 30 | def link_to_article(article) | 30 | def link_to_article(article) |
app/helpers/folder_helper.rb
| 1 | module FolderHelper | 1 | module FolderHelper |
| 2 | 2 | ||
| 3 | include ShortFilename | 3 | include ShortFilename |
| 4 | + include ArticleHelper | ||
| 4 | 5 | ||
| 5 | def list_articles(articles, recursive = false) | 6 | def list_articles(articles, recursive = false) |
| 6 | if !articles.blank? | 7 | if !articles.blank? |
| @@ -60,19 +61,10 @@ module FolderHelper | @@ -60,19 +61,10 @@ module FolderHelper | ||
| 60 | "icon-new icon-new%s" % klass.icon_name | 61 | "icon-new icon-new%s" % klass.icon_name |
| 61 | end | 62 | end |
| 62 | 63 | ||
| 63 | - def custom_options_for_article(article) | 64 | + def custom_options_for_article(article,tokenized_children) |
| 64 | @article = article | 65 | @article = article |
| 65 | - content_tag('h4', _('Visibility')) + | ||
| 66 | - content_tag('div', | ||
| 67 | - content_tag('div', | ||
| 68 | - radio_button(:article, :published, true) + | ||
| 69 | - content_tag('label', _('Public (visible to other people)'), :for => 'article_published_true') | ||
| 70 | - ) + | ||
| 71 | - content_tag('div', | ||
| 72 | - radio_button(:article, :published, false) + | ||
| 73 | - content_tag('label', _('Private'), :for => 'article_published_false') | ||
| 74 | - ) | ||
| 75 | - ) + | 66 | + |
| 67 | + visibility_options(article,tokenized_children) + | ||
| 76 | content_tag('div', | 68 | content_tag('div', |
| 77 | hidden_field_tag('article[accept_comments]', 0) | 69 | hidden_field_tag('article[accept_comments]', 0) |
| 78 | ) | 70 | ) |
| @@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
| 1 | +module TokenHelper | ||
| 2 | + | ||
| 3 | + def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...')) | ||
| 4 | + "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'" | ||
| 5 | + end | ||
| 6 | + | ||
| 7 | + def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {}) | ||
| 8 | + options[:min_chars] ||= 3 | ||
| 9 | + options[:hint_text] ||= _("Type in a search term") | ||
| 10 | + options[:no_results_text] ||= _("No results") | ||
| 11 | + options[:searching_text] ||= _("Searching...") | ||
| 12 | + options[:search_delay] ||= 1000 | ||
| 13 | + options[:prevent_duplicates] ||= true | ||
| 14 | + options[:backspace_delete_item] ||= false | ||
| 15 | + options[:focus] ||= false | ||
| 16 | + options[:avoid_enter] ||= true | ||
| 17 | + options[:on_result] ||= 'null' | ||
| 18 | + options[:on_add] ||= 'null' | ||
| 19 | + options[:on_delete] ||= 'null' | ||
| 20 | + options[:on_ready] ||= 'null' | ||
| 21 | + | ||
| 22 | + result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) | ||
| 23 | + result += javascript_tag("jQuery('##{element_id}') | ||
| 24 | + .tokenInput('#{url_for(search_action)}', { | ||
| 25 | + minChars: #{options[:min_chars].to_json}, | ||
| 26 | + prePopulate: #{options[:pre_populate].to_json}, | ||
| 27 | + hintText: #{options[:hint_text].to_json}, | ||
| 28 | + noResultsText: #{options[:no_results_text].to_json}, | ||
| 29 | + searchingText: #{options[:searching_text].to_json}, | ||
| 30 | + searchDelay: #{options[:serach_delay].to_json}, | ||
| 31 | + preventDuplicates: #{options[:prevent_duplicates].to_json}, | ||
| 32 | + backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, | ||
| 33 | + queryParam: #{name.to_json}, | ||
| 34 | + tokenLimit: #{options[:token_limit].to_json}, | ||
| 35 | + onResult: #{options[:on_result]}, | ||
| 36 | + onAdd: #{options[:on_add]}, | ||
| 37 | + onDelete: #{options[:on_delete]}, | ||
| 38 | + onReady: #{options[:on_ready]}, | ||
| 39 | + }); | ||
| 40 | + ") | ||
| 41 | + result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus] | ||
| 42 | + if options[:avoid_enter] | ||
| 43 | + result += javascript_tag("jQuery('#token-input-#{element_id}') | ||
| 44 | + .live('keydown', function(event){ | ||
| 45 | + if(event.keyCode == '13') return false; | ||
| 46 | + });") | ||
| 47 | + end | ||
| 48 | + result | ||
| 49 | + end | ||
| 50 | + | ||
| 51 | +end | ||
| 0 | \ No newline at end of file | 52 | \ No newline at end of file |
app/models/article.rb
| @@ -69,6 +69,7 @@ class Article < ActiveRecord::Base | @@ -69,6 +69,7 @@ class Article < ActiveRecord::Base | ||
| 69 | settings_items :allow_members_to_edit, :type => :boolean, :default => false | 69 | settings_items :allow_members_to_edit, :type => :boolean, :default => false |
| 70 | settings_items :moderate_comments, :type => :boolean, :default => false | 70 | settings_items :moderate_comments, :type => :boolean, :default => false |
| 71 | settings_items :followers, :type => Array, :default => [] | 71 | settings_items :followers, :type => Array, :default => [] |
| 72 | + has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' | ||
| 72 | 73 | ||
| 73 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' | 74 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' |
| 74 | 75 | ||
| @@ -470,7 +471,8 @@ class Article < ActiveRecord::Base | @@ -470,7 +471,8 @@ class Article < ActiveRecord::Base | ||
| 470 | 471 | ||
| 471 | def display_unpublished_article_to?(user) | 472 | def display_unpublished_article_to?(user) |
| 472 | user == author || allow_view_private_content?(user) || user == profile || | 473 | user == author || allow_view_private_content?(user) || user == profile || |
| 473 | - user.is_admin?(profile.environment) || user.is_admin?(profile) | 474 | + user.is_admin?(profile.environment) || user.is_admin?(profile) || |
| 475 | + article_privacy_exceptions.include?(user) | ||
| 474 | end | 476 | end |
| 475 | 477 | ||
| 476 | def display_to?(user = nil) | 478 | def display_to?(user = nil) |
app/models/person.rb
| @@ -64,6 +64,7 @@ class Person < Profile | @@ -64,6 +64,7 @@ class Person < Profile | ||
| 64 | has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy | 64 | has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy |
| 65 | 65 | ||
| 66 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' | 66 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' |
| 67 | + has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' | ||
| 67 | 68 | ||
| 68 | named_scope :more_popular, | 69 | named_scope :more_popular, |
| 69 | :select => "#{Profile.qualified_column_names}, count(friend_id) as total", | 70 | :select => "#{Profile.qualified_column_names}, count(friend_id) as total", |
app/views/cms/edit.rhtml
| 1 | <%= error_messages_for 'article' %> | 1 | <%= error_messages_for 'article' %> |
| 2 | +<%= javascript_include_tag "article.js" %> | ||
| 2 | 3 | ||
| 3 | <div class='<%= (environment.enabled?('media_panel') ? 'with_media_panel' : 'no_media_panel') %>'> | 4 | <div class='<%= (environment.enabled?('media_panel') ? 'with_media_panel' : 'no_media_panel') %>'> |
| 4 | <% labelled_form_for 'article', @article, :html => { :multipart => true, :class => @type } do |f| %> | 5 | <% labelled_form_for 'article', @article, :html => { :multipart => true, :class => @type } do |f| %> |
| @@ -33,7 +34,7 @@ | @@ -33,7 +34,7 @@ | ||
| 33 | <%= content_tag( 'small', _('Separate tags with commas') ) %> | 34 | <%= content_tag( 'small', _('Separate tags with commas') ) %> |
| 34 | 35 | ||
| 35 | <div id='edit-article-options'> | 36 | <div id='edit-article-options'> |
| 36 | - <%= options_for_article(@article) %> | 37 | + <%= options_for_article(@article, @tokenized_children) %> |
| 37 | </div> | 38 | </div> |
| 38 | 39 | ||
| 39 | <% button_bar do %> | 40 | <% button_bar do %> |
| @@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
| 1 | +class ArticlePrivacyExceptions < ActiveRecord::Migration | ||
| 2 | + def self.up | ||
| 3 | + create_table :article_privacy_exceptions, :id => false do |t| | ||
| 4 | + t.integer :article_id | ||
| 5 | + t.integer :person_id | ||
| 6 | + end | ||
| 7 | + end | ||
| 8 | + | ||
| 9 | + def self.down | ||
| 10 | + drop_table :article_privacy_exceptions | ||
| 11 | + end | ||
| 12 | +end |
db/schema.rb
| @@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
| 9 | # | 9 | # |
| 10 | # It's strongly recommended to check this file into your version control system. | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | ||
| 12 | -ActiveRecord::Schema.define(:version => 20131128161159) do | 12 | +ActiveRecord::Schema.define(:version => 20140108132730) do |
| 13 | 13 | ||
| 14 | create_table "abuse_reports", :force => true do |t| | 14 | create_table "abuse_reports", :force => true do |t| |
| 15 | t.integer "reporter_id" | 15 | t.integer "reporter_id" |
| @@ -46,6 +46,11 @@ ActiveRecord::Schema.define(:version => 20131128161159) do | @@ -46,6 +46,11 @@ ActiveRecord::Schema.define(:version => 20131128161159) do | ||
| 46 | add_index "action_tracker_notifications", ["profile_id", "action_tracker_id"], :name => "index_action_tracker_notif_on_prof_id_act_tracker_id", :unique => true | 46 | add_index "action_tracker_notifications", ["profile_id", "action_tracker_id"], :name => "index_action_tracker_notif_on_prof_id_act_tracker_id", :unique => true |
| 47 | add_index "action_tracker_notifications", ["profile_id"], :name => "index_action_tracker_notifications_on_profile_id" | 47 | add_index "action_tracker_notifications", ["profile_id"], :name => "index_action_tracker_notifications_on_profile_id" |
| 48 | 48 | ||
| 49 | + create_table "article_privacy_exceptions", :id => false, :force => true do |t| | ||
| 50 | + t.integer "article_id" | ||
| 51 | + t.integer "person_id" | ||
| 52 | + end | ||
| 53 | + | ||
| 49 | create_table "article_versions", :force => true do |t| | 54 | create_table "article_versions", :force => true do |t| |
| 50 | t.integer "article_id" | 55 | t.integer "article_id" |
| 51 | t.integer "version" | 56 | t.integer "version" |
features/edit_article.feature
| @@ -22,6 +22,70 @@ Feature: edit article | @@ -22,6 +22,70 @@ Feature: edit article | ||
| 22 | And I go to joaosilva's control panel | 22 | And I go to joaosilva's control panel |
| 23 | Then I should see "My Folder" | 23 | Then I should see "My Folder" |
| 24 | 24 | ||
| 25 | + @selenium | ||
| 26 | + Scenario: denied access folder for a not logged user | ||
| 27 | + Given the following communities | ||
| 28 | + | name | identifier | owner | | ||
| 29 | + | Free Software | freesoftware | joaosilva | | ||
| 30 | + And the following users | ||
| 31 | + | login | name | | ||
| 32 | + | mario | Mario Souto | | ||
| 33 | + | maria | Maria Silva | | ||
| 34 | + And "Mario Souto" is a member of "Free Software" | ||
| 35 | + And "Maria Silva" is a member of "Free Software" | ||
| 36 | + And I am on freesoftware's control panel | ||
| 37 | + And I follow "Manage Content" | ||
| 38 | + And I follow "New content" | ||
| 39 | + When I follow "Folder" | ||
| 40 | + And I fill in "Title" with "My Folder" | ||
| 41 | + And I choose "article_published_false" | ||
| 42 | + And I press "Save" | ||
| 43 | + And I log off | ||
| 44 | + And I go to /freesoftware/my-folder | ||
| 45 | + Then I should see "Access denied" | ||
| 46 | + | ||
| 47 | + @selenium | ||
| 48 | + Scenario: show exception users field when you choose the private option | ||
| 49 | + Given the following communities | ||
| 50 | + | name | identifier | owner | | ||
| 51 | + | Free Software | freesoftware | joaosilva | | ||
| 52 | + And the following users | ||
| 53 | + | login | name | | ||
| 54 | + | mario | Mario Souto | | ||
| 55 | + | maria | Maria Silva | | ||
| 56 | + And "Mario Souto" is a member of "Free Software" | ||
| 57 | + And "Maria Silva" is a member of "Free Software" | ||
| 58 | + And I am on freesoftware's control panel | ||
| 59 | + And I follow "Manage Content" | ||
| 60 | + And I follow "New content" | ||
| 61 | + When I follow "Folder" | ||
| 62 | + And I fill in "Title" with "My Folder" | ||
| 63 | + And I choose "article_published_false" | ||
| 64 | + Then I should see "Fill in the search field to add the exception users to see this content" | ||
| 65 | + | ||
| 66 | + @selenium | ||
| 67 | + Scenario: allowed user should see the content of a folder | ||
| 68 | + Given the following communities | ||
| 69 | + | name | identifier | owner | | ||
| 70 | + | Free Software | freesoftware | joaosilva | | ||
| 71 | + And the following users | ||
| 72 | + | login | name | | ||
| 73 | + | mario | Mario Souto | | ||
| 74 | + | maria | Maria Silva | | ||
| 75 | + And the following articles | ||
| 76 | + | owner | name | body | | ||
| 77 | + | freesoftware | My Folder | ... | | ||
| 78 | + And "Mario Souto" is a member of "Free Software" | ||
| 79 | + And "Maria Silva" is a member of "Free Software" | ||
| 80 | + And I go to /freesoftware/my-folder | ||
| 81 | + When I follow "Edit" | ||
| 82 | + And I choose "article_published_false" | ||
| 83 | + And I press "Save" | ||
| 84 | + And I add to "My Folder" the following exception "Maria Silva" | ||
| 85 | + And I am logged in as "maria" | ||
| 86 | + And I go to /freesoftware/my-folder | ||
| 87 | + Then I should see "My Folder" | ||
| 88 | + | ||
| 25 | Scenario: redirect to the created folder | 89 | Scenario: redirect to the created folder |
| 26 | Given I am on joaosilva's control panel | 90 | Given I am on joaosilva's control panel |
| 27 | And I follow "Manage Content" | 91 | And I follow "Manage Content" |
| @@ -40,6 +104,7 @@ Feature: edit article | @@ -40,6 +104,7 @@ Feature: edit article | ||
| 40 | When I follow "Cancel" within ".main-block" | 104 | When I follow "Cancel" within ".main-block" |
| 41 | Then I should be on joaosilva's cms | 105 | Then I should be on joaosilva's cms |
| 42 | 106 | ||
| 107 | + @selenium | ||
| 43 | Scenario: display tag list field when creating event | 108 | Scenario: display tag list field when creating event |
| 44 | Given I am on joaosilva's control panel | 109 | Given I am on joaosilva's control panel |
| 45 | And I follow "Manage Content" | 110 | And I follow "Manage Content" |
features/step_definitions/content_steps.rb
| @@ -8,3 +8,15 @@ When /^I create a content of type "([^\"]*)" with the following data$/ do |conte | @@ -8,3 +8,15 @@ When /^I create a content of type "([^\"]*)" with the following data$/ do |conte | ||
| 8 | 8 | ||
| 9 | click_button "Save" | 9 | click_button "Save" |
| 10 | end | 10 | end |
| 11 | + | ||
| 12 | +And /^I add to "([^\"]*)" the following exception "([^\"]*)"$/ do |article_name, user_exception| | ||
| 13 | + article = Article.find_by_name(article_name) | ||
| 14 | + community = article.profile | ||
| 15 | + raise "The article profile is not a community." unless community.class == Community | ||
| 16 | + | ||
| 17 | + my_user = community.members.find_by_name(user_exception) | ||
| 18 | + raise "Could not find #{user_exception} in #{community.name} community." if my_user.nil? | ||
| 19 | + | ||
| 20 | + article.article_privacy_exceptions << my_user | ||
| 21 | + article.save | ||
| 22 | +end | ||
| 11 | \ No newline at end of file | 23 | \ No newline at end of file |
public/javascripts/article.js
| @@ -172,4 +172,19 @@ jQuery(function($) { | @@ -172,4 +172,19 @@ jQuery(function($) { | ||
| 172 | return false; | 172 | return false; |
| 173 | }); | 173 | }); |
| 174 | 174 | ||
| 175 | + function show_hide_token_input() { | ||
| 176 | + if($("#article_published_false").attr('checked')) | ||
| 177 | + $("#text-input-search-exception-users").parent("div").css('display', 'block'); | ||
| 178 | + else | ||
| 179 | + $("#text-input-search-exception-users").parent("div").css('display', 'none'); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + if( $("#token-input-search-article-privacy-exceptions").length == 1 ) { | ||
| 183 | + show_hide_token_input(); | ||
| 184 | + | ||
| 185 | + //Hide / Show the text area | ||
| 186 | + $("#article_published_false").click(show_hide_token_input); | ||
| 187 | + $("#article_published_true").click(show_hide_token_input); | ||
| 188 | + } | ||
| 189 | + | ||
| 175 | }); | 190 | }); |