Commit 45e5189b55d3effe6b73b68fee7a0f5400b02185
Exists in
staging
and in
42 other branches
Merge branch 'work-assignment' into features
Conflicts: db/schema.rb test/functional/cms_controller_test.rb test/unit/article_test.rb
Showing
27 changed files
with
482 additions
and
41 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -16,7 +16,12 @@ class CmsController < MyProfileController |
16 | 16 | |
17 | 17 | before_filter :login_required, :except => [:suggest_an_article] |
18 | 18 | |
19 | - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish] do |c, user, profile| | |
19 | + protect_if :only => :upload_files do |c, user, profile| | |
20 | + article_id = c.params[:parent_id] | |
21 | + profile.articles.find(article_id).allow_create?(user) | |
22 | + end | |
23 | + | |
24 | + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files] do |c, user, profile| | |
20 | 25 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
21 | 26 | end |
22 | 27 | |
... | ... | @@ -92,7 +97,7 @@ class CmsController < MyProfileController |
92 | 97 | @article_types = [] |
93 | 98 | available_article_types.each do |type| |
94 | 99 | @article_types.push({ |
95 | - :name => type.name, | |
100 | + :class => type, | |
96 | 101 | :short_description => type.short_description, |
97 | 102 | :description => type.description |
98 | 103 | }) |
... | ... | @@ -117,6 +122,7 @@ class CmsController < MyProfileController |
117 | 122 | end |
118 | 123 | |
119 | 124 | @article.profile = profile |
125 | + @article.author = user | |
120 | 126 | @article.last_changed_by = user |
121 | 127 | |
122 | 128 | translations if @article.translatable? |
... | ... | @@ -154,7 +160,7 @@ class CmsController < MyProfileController |
154 | 160 | end |
155 | 161 | if request.post? && params[:uploaded_files] |
156 | 162 | params[:uploaded_files].each do |file| |
157 | - @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent) unless file == '' | |
163 | + @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent, :author => user) unless file == '' | |
158 | 164 | end |
159 | 165 | @errors = @uploaded_files.select { |f| f.errors.any? } |
160 | 166 | if @errors.any? | ... | ... |
app/helpers/folder_helper.rb
... | ... | @@ -52,8 +52,8 @@ module FolderHelper |
52 | 52 | end |
53 | 53 | end |
54 | 54 | |
55 | - def icon_for_new_article(type) | |
56 | - "icon-new icon-new%s" % type.constantize.icon_name | |
55 | + def icon_for_new_article(klass) | |
56 | + "icon-new icon-new%s" % klass.icon_name | |
57 | 57 | end |
58 | 58 | |
59 | 59 | def custom_options_for_article(article) | ... | ... |
app/models/article.rb
... | ... | @@ -13,6 +13,12 @@ class Article < ActiveRecord::Base |
13 | 13 | # xss_terminate plugin can't sanitize array fields |
14 | 14 | before_save :sanitize_tag_list |
15 | 15 | |
16 | + before_save do |article| | |
17 | + if article.author_id | |
18 | + article.author_name = Person.find(article.author_id).name | |
19 | + end | |
20 | + end | |
21 | + | |
16 | 22 | belongs_to :profile |
17 | 23 | validates_presence_of :profile_id, :name |
18 | 24 | validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } |
... | ... | @@ -20,6 +26,7 @@ class Article < ActiveRecord::Base |
20 | 26 | validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } |
21 | 27 | |
22 | 28 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
29 | + belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' | |
23 | 30 | |
24 | 31 | has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' |
25 | 32 | |
... | ... | @@ -289,7 +296,7 @@ class Article < ActiveRecord::Base |
289 | 296 | if last_comment |
290 | 297 | {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url} |
291 | 298 | else |
292 | - {:date => updated_at, :author_name => author.name, :author_url => author.url} | |
299 | + {:date => updated_at, :author_name => author_name, :author_url => author ? author.url : nil} | |
293 | 300 | end |
294 | 301 | end |
295 | 302 | |
... | ... | @@ -441,7 +448,7 @@ class Article < ActiveRecord::Base |
441 | 448 | end |
442 | 449 | |
443 | 450 | def allow_post_content?(user = nil) |
444 | - user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == self.creator)) | |
451 | + user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) | |
445 | 452 | end |
446 | 453 | |
447 | 454 | def allow_publish_content?(user = nil) |
... | ... | @@ -538,16 +545,8 @@ class Article < ActiveRecord::Base |
538 | 545 | false |
539 | 546 | end |
540 | 547 | |
541 | - def author | |
542 | - if reference_article | |
543 | - reference_article.author | |
544 | - else | |
545 | - last_changed_by || profile | |
546 | - end | |
547 | - end | |
548 | - | |
549 | 548 | def author_name |
550 | - setting[:author_name].blank? ? author.name : setting[:author_name] | |
549 | + author ? author.name : setting[:author_name] | |
551 | 550 | end |
552 | 551 | |
553 | 552 | alias :active_record_cache_key :cache_key |
... | ... | @@ -572,11 +571,6 @@ class Article < ActiveRecord::Base |
572 | 571 | truncate sanitize_html(self.lead), :length => 170, :omission => '...' |
573 | 572 | end |
574 | 573 | |
575 | - def creator | |
576 | - creator_id = versions[0][:last_changed_by_id] | |
577 | - creator_id && Profile.find(creator_id) | |
578 | - end | |
579 | - | |
580 | 574 | def notifiable? |
581 | 575 | false |
582 | 576 | end | ... | ... |
app/models/event.rb
... | ... | @@ -38,7 +38,7 @@ class Event < Article |
38 | 38 | filter_iframes :body, :link, :address, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe } |
39 | 39 | |
40 | 40 | def self.description |
41 | - _('A calendar event') | |
41 | + _('A calendar event.') | |
42 | 42 | end |
43 | 43 | |
44 | 44 | def self.short_description | ... | ... |
app/models/person.rb
... | ... | @@ -54,6 +54,8 @@ class Person < Profile |
54 | 54 | |
55 | 55 | has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy |
56 | 56 | |
57 | + has_many :creations, :class_name => 'Article', :foreign_key => :author_id | |
58 | + | |
57 | 59 | named_scope :more_popular, |
58 | 60 | :select => "#{Profile.qualified_column_names}, count(friend_id) as total", |
59 | 61 | :group => Profile.qualified_column_names, | ... | ... |
app/models/raw_html_article.rb
... | ... | @@ -5,11 +5,11 @@ class RawHTMLArticle < TextArticle |
5 | 5 | end |
6 | 6 | |
7 | 7 | def self.short_description |
8 | - _('Raw HTML text article.') | |
8 | + _('Raw HTML text article') | |
9 | 9 | end |
10 | 10 | |
11 | 11 | def self.description |
12 | - _('Allows HTML without filter (only for admins)') | |
12 | + _('Allows HTML without filter (only for admins).') | |
13 | 13 | end |
14 | 14 | |
15 | 15 | xss_terminate :only => [ ] | ... | ... |
app/models/tiny_mce_article.rb
app/views/cms/select_article_type.rhtml
... | ... | @@ -2,9 +2,9 @@ |
2 | 2 | |
3 | 3 | <ul id="article_types"> |
4 | 4 | <% for type in @article_types %> |
5 | - <% action = type[:name] == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:name]} %> | |
5 | + <% action = type[:class].name == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:class].name} %> | |
6 | 6 | <% content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %> |
7 | - <li class="<%= icon_for_new_article(type[:name]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | |
7 | + <li class="<%= icon_for_new_article(type[:class]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | |
8 | 8 | <strong><%= type[:short_description] %></strong> |
9 | 9 | <div class='description'><%= type[:description] %></div> |
10 | 10 | </li> | ... | ... |
app/views/content_viewer/_article_toolbar.rhtml
... | ... | @@ -34,11 +34,11 @@ |
34 | 34 | <%= expirable_button @page, :locale, content, url %> |
35 | 35 | <% end %> |
36 | 36 | |
37 | - <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> | |
37 | + <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) if !remove_content_button(:new) %> | |
38 | 38 | <% end %> |
39 | 39 | |
40 | 40 | <% if @page.accept_uploads? && @page.allow_create?(user) %> |
41 | - <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> | |
41 | + <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) if !remove_content_button(:upload)%> | |
42 | 42 | <% end %> |
43 | 43 | |
44 | 44 | <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +class AddAuthorIdToArticle < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + add_column :articles, :author_id, :integer | |
4 | + add_column :article_versions, :author_id, :integer | |
5 | + end | |
6 | + | |
7 | + def self.down | |
8 | + remove_column :articles, :author_id | |
9 | + remove_column :article_versions, :author_id, :integer | |
10 | + end | |
11 | +end | ... | ... |
db/migrate/20121024222938_set_authors_based_on_article_versions.rb
0 → 100644
... | ... | @@ -0,0 +1,9 @@ |
1 | +class SetAuthorsBasedOnArticleVersions < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + update('UPDATE articles SET author_id = (SELECT profiles.id FROM articles as a INNER JOIN article_versions ON a.id = article_versions.article_id INNER JOIN profiles ON profiles.id = article_versions.last_changed_by_id WHERE article_versions.version = 1 AND articles.id = a.id)') | |
4 | + end | |
5 | + | |
6 | + def self.down | |
7 | + say "Can not be revesed!" | |
8 | + end | |
9 | +end | ... | ... |
db/schema.rb
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | # |
10 | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | |
12 | -ActiveRecord::Schema.define(:version => 20121008185303) do | |
12 | +ActiveRecord::Schema.define(:version => 20121024222938) do | |
13 | 13 | |
14 | 14 | create_table "abuse_reports", :force => true do |t| |
15 | 15 | t.integer "reporter_id" |
... | ... | @@ -86,6 +86,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
86 | 86 | t.string "language" |
87 | 87 | t.string "source_name" |
88 | 88 | t.integer "license_id" |
89 | + t.integer "author_id" | |
89 | 90 | end |
90 | 91 | |
91 | 92 | create_table "articles", :force => true do |t| |
... | ... | @@ -127,6 +128,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
127 | 128 | t.string "language" |
128 | 129 | t.string "source_name" |
129 | 130 | t.integer "license_id" |
131 | + t.integer "author_id" | |
130 | 132 | end |
131 | 133 | |
132 | 134 | add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" | ... | ... |
lib/noosfero/plugin.rb
... | ... | @@ -130,7 +130,7 @@ class Noosfero::Plugin |
130 | 130 | end |
131 | 131 | |
132 | 132 | # -> Adds plugin-specific content types to CMS |
133 | - # returns = { content type class } | |
133 | + # returns = [ContentClass1, ContentClass2, ...] | |
134 | 134 | def content_types |
135 | 135 | nil |
136 | 136 | end |
... | ... | @@ -384,7 +384,9 @@ class Noosfero::Plugin |
384 | 384 | private |
385 | 385 | |
386 | 386 | def content_actions |
387 | - %w[edit delete spread locale suggest home] | |
387 | + #FIXME 'new' and 'upload' only works for content_remove. It should work for | |
388 | + #content_expire too. | |
389 | + %w[edit delete spread locale suggest home new upload] | |
388 | 390 | end |
389 | 391 | |
390 | 392 | end | ... | ... |
... | ... | @@ -0,0 +1,52 @@ |
1 | +class WorkAssignmentPlugin < Noosfero::Plugin | |
2 | + | |
3 | + def self.plugin_name | |
4 | + "Work Assignment" | |
5 | + end | |
6 | + | |
7 | + def self.plugin_description | |
8 | + _("New kind of content for organizations.") | |
9 | + end | |
10 | + | |
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))) | |
14 | + end | |
15 | + | |
16 | + def self.is_submission?(content) | |
17 | + content && content.parent && content.parent.parent && content.parent.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment) | |
18 | + end | |
19 | + | |
20 | + def content_types | |
21 | + [WorkAssignmentPlugin::WorkAssignment] if context.profile.organization? | |
22 | + end | |
23 | + | |
24 | + def stylesheet? | |
25 | + true | |
26 | + end | |
27 | + | |
28 | + def content_remove_new(content) | |
29 | + content.kind_of?(WorkAssignmentPlugin::WorkAssignment) | |
30 | + end | |
31 | + | |
32 | + def content_remove_upload(content) | |
33 | + !content.profile.members.include?(context.send(:user)) | |
34 | + end | |
35 | + | |
36 | + def content_viewer_controller_filters | |
37 | + block = lambda do | |
38 | + path = params[:page].join('/') | |
39 | + content = profile.articles.find_by_path(path) | |
40 | + | |
41 | + if WorkAssignmentPlugin.is_submission?(content) && !WorkAssignmentPlugin.can_download_submission?(user, content) | |
42 | + render_access_denied | |
43 | + end | |
44 | + end | |
45 | + | |
46 | + { :type => 'before_filter', | |
47 | + :method_name => 'work_assingment_only_admin_or_owner_download', | |
48 | + :options => {:only => 'view_page'}, | |
49 | + :block => block } | |
50 | + end | |
51 | + | |
52 | +end | ... | ... |
plugins/work_assignment/lib/work_assignment_plugin/helper.rb
0 → 100644
... | ... | @@ -0,0 +1,59 @@ |
1 | +module WorkAssignmentPlugin::Helper | |
2 | + def display_submissions(work_assignment, user) | |
3 | + return if work_assignment.submissions.empty? | |
4 | + content_tag('table', | |
5 | + content_tag('tr', | |
6 | + content_tag('th', _('Author'), :style => 'width: 50%') + | |
7 | + content_tag('th', _('Submission date')) + | |
8 | + content_tag('th', _('Versions'), :style => 'text-align: center') + | |
9 | + content_tag('th', '') | |
10 | + ) + | |
11 | + work_assignment.children.map {|author_folder| display_author_folder(author_folder, user)}.join("\n") | |
12 | + ) | |
13 | + end | |
14 | + | |
15 | + def display_author_folder(author_folder, user) | |
16 | + return if author_folder.children.empty? | |
17 | + content_tag('tr', | |
18 | + content_tag('td', link_to_last_submission(author_folder, user)) + | |
19 | + content_tag('td', time_format(author_folder.children.last.created_at)) + | |
20 | + 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)) | |
22 | + ) + | |
23 | + author_folder.children.map {|submission| display_submission(submission, user)}.join("\n") | |
24 | + end | |
25 | + | |
26 | + def display_submission(submission, user) | |
27 | + content_tag('tr', | |
28 | + content_tag('td', link_to_submission(submission, user)) + | |
29 | + content_tag('td', time_format(submission.created_at), :colspan => 3), | |
30 | + :class => "submission-from-#{submission.parent.id}", | |
31 | + :style => 'display: none' | |
32 | + ) | |
33 | + end | |
34 | + | |
35 | + def link_to_submission(submission, user) | |
36 | + if WorkAssignmentPlugin.can_download_submission?(user, submission) | |
37 | + link_to(submission.name, submission.url) | |
38 | + else | |
39 | + submission.name | |
40 | + end | |
41 | + end | |
42 | + | |
43 | + | |
44 | + def link_to_last_submission(author_folder, user) | |
45 | + if WorkAssignmentPlugin.can_download_submission?(user, author_folder.children.last) | |
46 | + link_to(author_folder.name, author_folder.children.last.url) | |
47 | + else | |
48 | + author_folder.name | |
49 | + end | |
50 | + end | |
51 | + # FIXME Copied from custom-froms. Consider passing it to core... | |
52 | + def time_format(time) | |
53 | + minutes = (time.min == 0) ? '' : ':%M' | |
54 | + hour = (time.hour == 0 && minutes.blank?) ? '' : ' %H' | |
55 | + h = hour.blank? ? '' : 'h' | |
56 | + time.strftime("%Y-%m-%d#{hour+minutes+h}") | |
57 | + end | |
58 | + | |
59 | +end | ... | ... |
plugins/work_assignment/lib/work_assignment_plugin/work_assignment.rb
0 → 100644
... | ... | @@ -0,0 +1,52 @@ |
1 | +class WorkAssignmentPlugin::WorkAssignment < Folder | |
2 | + | |
3 | + after_save do |work_assignment| | |
4 | + work_assignment.children.select {|child| child.kind_of?(UploadedFile)}.each do |submission| | |
5 | + author_folder = work_assignment.find_or_create_author_folder(submission.author) | |
6 | + submission.name = versioned_name(submission, author_folder) if !(submission.name =~ /\(V[0-9]*\)/) | |
7 | + submission.parent = author_folder | |
8 | + submission.save! | |
9 | + end | |
10 | + end | |
11 | + | |
12 | + settings_items :publish_submissions, :type => :boolean, :default => false | |
13 | + | |
14 | + def self.icon_name(article = nil) | |
15 | + 'work-assignment' | |
16 | + end | |
17 | + | |
18 | + def self.short_description | |
19 | + _('Work Assignment') | |
20 | + end | |
21 | + | |
22 | + def self.description | |
23 | + _('Defines a work to be done by the members and receives their submissions about this work.') | |
24 | + end | |
25 | + | |
26 | + def self.versioned_name(submission, folder) | |
27 | + "(V#{folder.children.count + 1}) #{submission.name}" | |
28 | + end | |
29 | + | |
30 | + def accept_comments? | |
31 | + true | |
32 | + end | |
33 | + | |
34 | + def allow_create?(user) | |
35 | + profile.members.include?(user) | |
36 | + end | |
37 | + | |
38 | + def to_html(options = {}) | |
39 | + lambda do | |
40 | + render :file => 'content_viewer/work_assignment.html.erb' | |
41 | + end | |
42 | + end | |
43 | + | |
44 | + def find_or_create_author_folder(author) | |
45 | + children.find_by_slug(author.identifier) || Folder.create!(:name => author.name, :slug => author.identifier, :parent => self, :profile => profile) | |
46 | + end | |
47 | + | |
48 | + def submissions | |
49 | + children.map(&:children).flatten.compact | |
50 | + end | |
51 | + | |
52 | +end | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +jQuery(".view-author-versions").each(function(index, bt){ | |
2 | + jQuery(bt).button({ | |
3 | + icons: { | |
4 | + primary: "ui-icon-info" | |
5 | + }, | |
6 | + text: false | |
7 | + }); | |
8 | + bt.onclick = function(){ | |
9 | + var folderId = this.getAttribute("data-folder-id"); | |
10 | + var tr = jQuery(".submission-from-"+folderId); | |
11 | + if ( tr[0].style.display == "none" ) | |
12 | + tr.show(); | |
13 | + else | |
14 | + tr.hide(); | |
15 | + } | |
16 | +}); | ... | ... |
plugins/work_assignment/test/functional/cms_controller_test.rb
0 → 100644
... | ... | @@ -0,0 +1,34 @@ |
1 | +require 'test_helper' | |
2 | +require 'cms_controller' | |
3 | + | |
4 | +# Re-raise errors caught by the controller. | |
5 | +class CmsController; def rescue_action(e) raise e end; end | |
6 | + | |
7 | +class CmsControllerTest < ActionController::TestCase | |
8 | + | |
9 | + def setup | |
10 | + @controller = CmsController.new | |
11 | + @request = ActionController::TestRequest.new | |
12 | + @response = ActionController::TestResponse.new | |
13 | + @person = create_user('test_user').person | |
14 | + login_as :test_user | |
15 | + end | |
16 | + | |
17 | + attr_accessor :person | |
18 | + | |
19 | + 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 | |
24 | + assert_response :forbidden | |
25 | + assert_template 'access_denied.rhtml' | |
26 | + | |
27 | + organization.add_member(person) | |
28 | + | |
29 | + get :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id | |
30 | + assert_response :success | |
31 | + end | |
32 | + | |
33 | +end | |
34 | + | ... | ... |
plugins/work_assignment/test/functional/content_viewer_controller_test.rb
0 → 100644
... | ... | @@ -0,0 +1,41 @@ |
1 | +require 'test_helper' | |
2 | +require 'content_viewer_controller' | |
3 | + | |
4 | +# Re-raise errors caught by the controller. | |
5 | +class ContentViewerController; def rescue_action(e) raise e end; end | |
6 | + | |
7 | +class ContentViewerControllerTest < ActionController::TestCase | |
8 | + | |
9 | + def setup | |
10 | + @controller = ContentViewerController.new | |
11 | + @request = ActionController::TestRequest.new | |
12 | + @response = ActionController::TestResponse.new | |
13 | + | |
14 | + @organization = fast_create(Organization) | |
15 | + @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => @organization) | |
16 | + @person = create_user('test_user').person | |
17 | + @environment = @organization.environment | |
18 | + @environment.enable_plugin(WorkAssignmentPlugin) | |
19 | + @environment.save! | |
20 | + login_as(:test_user) | |
21 | + end | |
22 | + attr_reader :organization, :person, :work_assignment | |
23 | + | |
24 | + should 'can download work_assignment' do | |
25 | + random_member = fast_create(Person) | |
26 | + organization.add_member(random_member) | |
27 | + folder = work_assignment.find_or_create_author_folder(random_member) | |
28 | + submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder) | |
29 | + WorkAssignmentPlugin.stubs(:can_download_submission?).returns(false) | |
30 | + | |
31 | + get :view_page, :profile => organization.identifier, :page => submission.explode_path | |
32 | + assert_response :forbidden | |
33 | + assert_template 'access_denied.rhtml' | |
34 | + | |
35 | + WorkAssignmentPlugin.stubs(:can_download_submission?).returns(true) | |
36 | + | |
37 | + get :view_page, :profile => organization.identifier, :page => submission.explode_path | |
38 | + assert_response :success | |
39 | + end | |
40 | + | |
41 | +end | ... | ... |
plugins/work_assignment/test/unit/work_assingment_plugin/work_assignment_test.rb
0 → 100644
... | ... | @@ -0,0 +1,43 @@ |
1 | +require "test_helper" | |
2 | + | |
3 | +class WorkAssignmentTest < ActiveSupport::TestCase | |
4 | + should 'find or create sub-folder based on author identifier' do | |
5 | + profile = fast_create(Profile) | |
6 | + author = fast_create(Person) | |
7 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Sample Work Assignment', :profile => profile) | |
8 | + assert_nil work_assignment.children.find_by_slug(author.identifier) | |
9 | + | |
10 | + folder = work_assignment.find_or_create_author_folder(author) | |
11 | + assert_not_nil work_assignment.children.find_by_slug(author.identifier) | |
12 | + assert_equal folder, work_assignment.find_or_create_author_folder(author) | |
13 | + end | |
14 | + | |
15 | + should 'return versioned name' do | |
16 | + folder = fast_create(Folder) | |
17 | + profile = fast_create(Profile) | |
18 | + a1 = Article.create!(:name => "Article 1", :profile => profile) | |
19 | + a2 = Article.create!(:name => "Article 2", :profile => profile) | |
20 | + a3 = Article.create!(:name => "Article 3", :profile => profile) | |
21 | + klass = WorkAssignmentPlugin::WorkAssignment | |
22 | + | |
23 | + assert_equal "(V1) #{a1.name}", klass.versioned_name(a1, folder) | |
24 | + | |
25 | + a1.parent = folder | |
26 | + a1.save! | |
27 | + assert_equal "(V2) #{a2.name}", klass.versioned_name(a2, folder) | |
28 | + | |
29 | + a2.parent = folder | |
30 | + a2.save! | |
31 | + assert_equal "(V3) #{a3.name}", klass.versioned_name(a3, folder) | |
32 | + end | |
33 | + | |
34 | + should 'move submission to its correct author folder' do | |
35 | + organization = fast_create(Organization) | |
36 | + author = fast_create(Person) | |
37 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Sample Work Assignment', :profile => organization) | |
38 | + submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => work_assignment, :author => author) | |
39 | + | |
40 | + author_folder = work_assignment.find_or_create_author_folder(author) | |
41 | + assert author_folder, submission.parent | |
42 | + end | |
43 | +end | ... | ... |
plugins/work_assignment/test/unit/work_assingment_plugin_test.rb
0 → 100644
... | ... | @@ -0,0 +1,57 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class WorkAssignmentPluginTest < ActiveSupport::TestCase | |
4 | + should 'verify if a content is a work_assignment submission' do | |
5 | + organization = fast_create(Organization) | |
6 | + content = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization) | |
7 | + assert !WorkAssignmentPlugin.is_submission?(content) | |
8 | + | |
9 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | |
10 | + content.parent = work_assignment | |
11 | + content.save! | |
12 | + assert !WorkAssignmentPlugin.is_submission?(content) | |
13 | + | |
14 | + author_folder = work_assignment.find_or_create_author_folder(fast_create(Person)) | |
15 | + content.parent = author_folder | |
16 | + content.save! | |
17 | + assert WorkAssignmentPlugin.is_submission?(content) | |
18 | + end | |
19 | + | |
20 | + should 'be able to download submission if work_assignment published submissions' do | |
21 | + submission = create_submission | |
22 | + assert !WorkAssignmentPlugin.can_download_submission?(nil, submission) | |
23 | + | |
24 | + work_assignment = submission.parent.parent | |
25 | + work_assignment.publish_submissions = true | |
26 | + work_assignment.save! | |
27 | + assert WorkAssignmentPlugin.can_download_submission?(nil, submission) | |
28 | + end | |
29 | + | |
30 | + should 'be able to download submission if the user is author of it' do | |
31 | + person = fast_create(Person) | |
32 | + submission = create_submission | |
33 | + assert !WorkAssignmentPlugin.can_download_submission?(person, submission) | |
34 | + | |
35 | + submission.author = person | |
36 | + submission.save! | |
37 | + assert WorkAssignmentPlugin.can_download_submission?(person, submission) | |
38 | + end | |
39 | + | |
40 | + should 'be able to download submission if the user has the view_private_content permission on the profile' do | |
41 | + person = fast_create(Person) | |
42 | + submission = create_submission | |
43 | + assert !WorkAssignmentPlugin.can_download_submission?(person, submission) | |
44 | + | |
45 | + moderator = create_user_with_permission('moderator', 'view_private_content', submission.profile) | |
46 | + assert WorkAssignmentPlugin.can_download_submission?(moderator, submission) | |
47 | + end | |
48 | + | |
49 | + private | |
50 | + | |
51 | + def create_submission | |
52 | + organization = fast_create(Organization) | |
53 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | |
54 | + author_folder = work_assignment.find_or_create_author_folder(fast_create(Person)) | |
55 | + UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => author_folder) | |
56 | + end | |
57 | +end | ... | ... |
plugins/work_assignment/views/cms/work_assignment_plugin/_work_assignment.html.erb
0 → 100644
plugins/work_assignment/views/content_viewer/work_assignment.html.erb
0 → 100644
test/functional/cms_controller_test.rb
... | ... | @@ -1583,6 +1583,28 @@ class CmsControllerTest < ActionController::TestCase |
1583 | 1583 | assert_equal f2, article.parent |
1584 | 1584 | end |
1585 | 1585 | |
1586 | + should 'set author when creating article' do | |
1587 | + login_as(profile.identifier) | |
1588 | + | |
1589 | + post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :article => { :name => 'Sample Article', :body => 'content ...' } | |
1590 | + | |
1591 | + a = profile.articles.find_by_path('sample-article') | |
1592 | + assert_not_nil a | |
1593 | + assert_equal profile, a.author | |
1594 | + end | |
1595 | + | |
1596 | + should 'not allow user upload files if he can not create on the parent folder' do | |
1597 | + c = Community.create!(:name => 'test_comm', :identifier => 'test_comm') | |
1598 | + u = create_user('test_user') | |
1599 | + a = c.articles.create!(:name => 'test_article') | |
1600 | + a.stubs(:allow_create?).with(u).returns(true) | |
1601 | + login_as :test_user | |
1602 | + | |
1603 | + get :upload_files, :profile => c.identifier, :parent_id => a.id | |
1604 | + assert_response :forbidden | |
1605 | + assert_template 'access_denied.rhtml' | |
1606 | + end | |
1607 | + | |
1586 | 1608 | protected |
1587 | 1609 | |
1588 | 1610 | # FIXME this is to avoid adding an extra dependency for a proper JSON parser. | ... | ... |
test/unit/article_test.rb
... | ... | @@ -708,14 +708,6 @@ class ArticleTest < ActiveSupport::TestCase |
708 | 708 | assert_equal a.url, a.view_url |
709 | 709 | end |
710 | 710 | |
711 | - should 'know its author' do | |
712 | - assert_equal profile, Article.new(:last_changed_by => profile).author | |
713 | - end | |
714 | - | |
715 | - should 'use owning profile as author when we dont know who did the last change' do | |
716 | - assert_equal profile, Article.new(:last_changed_by => nil, :profile => profile).author | |
717 | - end | |
718 | - | |
719 | 711 | should 'have published_at' do |
720 | 712 | assert_respond_to Article.new, :published_at |
721 | 713 | end |
... | ... | @@ -1372,7 +1364,7 @@ class ArticleTest < ActiveSupport::TestCase |
1372 | 1364 | assert Article.method_defined?('author_name') |
1373 | 1365 | end |
1374 | 1366 | |
1375 | - should "the author_name returns the name od the article's author" do | |
1367 | + should "the author_name returns the name of the article's author" do | |
1376 | 1368 | author = mock() |
1377 | 1369 | author.expects(:name).returns('author name') |
1378 | 1370 | a = Article.new |
... | ... | @@ -1818,4 +1810,25 @@ class ArticleTest < ActiveSupport::TestCase |
1818 | 1810 | assert a1.errors.invalid?(:parent_id) |
1819 | 1811 | end |
1820 | 1812 | |
1813 | + should 'be able to have an author' do | |
1814 | + author = fast_create(Person) | |
1815 | + article = Article.new | |
1816 | + assert_nothing_raised do | |
1817 | + article.author = author | |
1818 | + end | |
1819 | + end | |
1820 | + | |
1821 | + should 'set author_name before saving article if there is an author' do | |
1822 | + author = fast_create(Person) | |
1823 | + article = fast_create(Article, :profile_id => fast_create(Profile).id) | |
1824 | + article.author = author | |
1825 | + article.save! | |
1826 | + assert_equal author.name, article.author_name | |
1827 | + | |
1828 | + author_name = author.name | |
1829 | + author.destroy | |
1830 | + article.reload | |
1831 | + assert_equal author_name, article.author_name | |
1832 | + end | |
1833 | + | |
1821 | 1834 | end | ... | ... |
test/unit/person_test.rb
... | ... | @@ -1262,4 +1262,15 @@ class PersonTest < ActiveSupport::TestCase |
1262 | 1262 | |
1263 | 1263 | assert person.has_permission?('bli', Profile.new) |
1264 | 1264 | end |
1265 | + | |
1266 | + should 'have creations' do | |
1267 | + person = create_user('some-user').person | |
1268 | + a1 = fast_create(Article, :author_id => person.id) | |
1269 | + a2 = fast_create(Article, :author_id => person.id) | |
1270 | + a3 = fast_create(Article) | |
1271 | + | |
1272 | + assert_includes person.creations, a1 | |
1273 | + assert_includes person.creations, a2 | |
1274 | + assert_not_includes person.creations, a3 | |
1275 | + end | |
1265 | 1276 | end | ... | ... |