Commit 5e1957f3b4cfb65788b99a126a940ca7dfe6dca5

Authored by Antonio Terceiro
2 parents d9a2d31d c13119fb

Merge branch 'work_assignment_master_rebase' into 'master'

Work assignment master rebase

The last version of the Work Assignment plugin, increased by Universidade de Brasília team.

The plugin purpose is to keep versioned files, result of a work and to notify people by email about new uploaded files. Users can also change the visibility of their files, if the feature is set on Work Assignment settings.

See merge request !420
app/controllers/my_profile/cms_controller.rb
@@ -214,6 +214,7 @@ class CmsController < MyProfileController @@ -214,6 +214,7 @@ class CmsController < MyProfileController
214 if @errors.any? 214 if @errors.any?
215 render :action => 'upload_files', :parent_id => @parent_id 215 render :action => 'upload_files', :parent_id => @parent_id
216 else 216 else
  217 + session[:notice] = _('File(s) successfully uploaded')
217 if @back_to 218 if @back_to
218 redirect_to @back_to 219 redirect_to @back_to
219 elsif @parent 220 elsif @parent
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 +
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" %>