Commit 4d9daa44dbf61490640b32a8fb9f6f49f0f8b152
Exists in
staging
Merge branch 'master' into staging
Showing
136 changed files
with
1279 additions
and
399 deletions
Show diff stats
.travis.yml
RELEASING.md
| ... | ... | @@ -3,37 +3,30 @@ Noosfero release tasks |
| 3 | 3 | |
| 4 | 4 | This file documents release-related activities. |
| 5 | 5 | |
| 6 | -Working with translations | |
| 7 | -------------------------- | |
| 8 | - | |
| 9 | -* Update translation files: `rake updatepo`. Then `git commit` them. | |
| 10 | -* Send the PO files to the translators. | |
| 11 | -* Get the PO files back from translators, put in `po/` under the correct language name (e.,g. `po/pt_BR/`) and `git commit`. | |
| 12 | -* test translations: `rake makemo` and browse the application on the web. | |
| 13 | - | |
| 14 | 6 | Releasing noosfero |
| 15 | 7 | ------------------ |
| 16 | 8 | |
| 17 | -Considering you are on a Debian GNU/Linux or Debian-based system | |
| 9 | +Considering you are on a Debian GNU/Linux or Debian-based system, the following | |
| 10 | +packages are required during the release process: | |
| 18 | 11 | |
| 19 | - # apt-get install devscripts debhelper | |
| 12 | +``` | |
| 13 | +# apt install git devscripts debhelper | |
| 14 | +``` | |
| 20 | 15 | |
| 21 | 16 | To prepare a release of noosfero, you must follow the steps below: |
| 22 | 17 | |
| 23 | -* Finish all requirements and bugs assigned to the to-be-released version | |
| 18 | +* Disable the automatic pushing of translation updates in weblate. | |
| 24 | 19 | * Make sure all tests pass |
| 25 | -* Write release notes at the version's wiki topic | |
| 26 | 20 | * Generate packages with `rake noosfero:release[(stable|test)]`. This task will: |
| 27 | 21 | * Update the version in lib/noosfero.rb and debian/changelog. |
| 28 | 22 | * Create the tarbal and the deb pkg under pkg/ directory. |
| 29 | 23 | * Create a git tag and push it. |
| 30 | - * Upload the pkg to the configured repository (if configured) on ~/.dput.cf. | |
| 24 | + * Upload the packages to the configured repository (if configured) on ~/.dput.cf. | |
| 31 | 25 | * Test that the tarball and deb package are ok |
| 32 | -* Go to the version's wiki topic and edit it to reflect the new reality | |
| 33 | -* Edit the topic WebPreferences and update DEBIAN_REPOSITORY_TOPICS setting | |
| 34 | -* Attach the generated packages to that topic. Before attaching calculate the sha1 of the package (with sha1sum and paste the SHA1 hash as comment in the attachment form) | |
| 35 | -* Download the attached and verify the MD5 hash | |
| 36 | 26 | * Update an eventual demonstration version that you run. |
| 37 | -* Write an announcement e-mail to the relevant mailing lists pointing to the release notes, and maybe to the demonstration version. | |
| 27 | +* Write an announcement e-mail to the relevant mailing lists pointing to the | |
| 28 | + release notes, and maybe to the demonstration version. | |
| 29 | +* Re-enable the automatic pushing of trasnlatio updates in weblate. | |
| 38 | 30 | |
| 39 | -If you had any problem during these steps, you can do `rake clobber_package` to completely delete the generated packages and start the process again. | |
| 31 | +If you had any problem during these steps, you can do `rake clobber_package` to | |
| 32 | +completely delete the generated packages and start the process again. | ... | ... |
app/controllers/box_organizer_controller.rb
| ... | ... | @@ -83,12 +83,9 @@ class BoxOrganizerController < ApplicationController |
| 83 | 83 | |
| 84 | 84 | def save |
| 85 | 85 | @block = boxes_holder.blocks.find(params[:id]) |
| 86 | - if @block.kind_of?(RawHTMLBlock) && !user.is_admin?(environment) | |
| 87 | - render_access_denied | |
| 88 | - else | |
| 89 | - @block.update(params[:block]) | |
| 90 | - redirect_to :action => 'index' | |
| 91 | - end | |
| 86 | + return render_access_denied unless @block.editable?(user) | |
| 87 | + @block.update(params[:block]) | |
| 88 | + redirect_to :action => 'index' | |
| 92 | 89 | end |
| 93 | 90 | |
| 94 | 91 | def boxes_editor? | ... | ... |
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -32,7 +32,8 @@ class CmsController < MyProfileController |
| 32 | 32 | end |
| 33 | 33 | |
| 34 | 34 | protect_if :only => [:new, :upload_files] do |c, user, profile| |
| 35 | - parent = profile.articles.find_by_id(c.params[:parent_id]) | |
| 35 | + parent_id = c.params[:article].present? ? c.params[:article][:parent_id] : c.params[:parent_id] | |
| 36 | + parent = profile.articles.find_by_id(parent_id) | |
| 36 | 37 | user && user.can_post_content?(profile, parent) |
| 37 | 38 | end |
| 38 | 39 | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
| ... | ... | @@ -2,8 +2,27 @@ class ProfileMembersController < MyProfileController |
| 2 | 2 | protect 'manage_memberships', :profile |
| 3 | 3 | |
| 4 | 4 | def index |
| 5 | - @members = profile.members_by_name | |
| 6 | - @member_role = environment.roles.find_by_name('member') | |
| 5 | + @filters = params[:filters] || {:roles => []} | |
| 6 | + all_roles = Profile::Roles.organization_member_roles(environment.id) | Profile::Roles.organization_custom_roles(environment.id, profile.id) | |
| 7 | + @filters[:roles] = all_roles unless @filters[:roles].present? | |
| 8 | + @data = {} | |
| 9 | + field = 'name' | |
| 10 | + field = 'email' if @filters[:name] =~ /\@/ | |
| 11 | + | |
| 12 | + @data[:members] = profile.members_by(field,@filters[:name]).by_role(@filters[:roles]) | |
| 13 | + session[:members_filtered] = @data[:members].map{|m|m.id} if request.post? | |
| 14 | + @data[:roles] = all_roles | |
| 15 | + | |
| 16 | + end | |
| 17 | + | |
| 18 | + def send_mail | |
| 19 | + session[:members_filtered] = params[:members_filtered].select{|value| value!="0"} | |
| 20 | + if session[:members_filtered].present? | |
| 21 | + redirect_to :controller => :profile, :action => :send_mail | |
| 22 | + else | |
| 23 | + session[:notice] = _("Select at least one member.") | |
| 24 | + redirect_to :action => :index | |
| 25 | + end | |
| 7 | 26 | end |
| 8 | 27 | |
| 9 | 28 | def update_roles |
| ... | ... | @@ -156,4 +175,13 @@ class ProfileMembersController < MyProfileController |
| 156 | 175 | end |
| 157 | 176 | end |
| 158 | 177 | |
| 178 | + def search_members | |
| 179 | + field = 'name' | |
| 180 | + field = 'email' if params[:filter_name] =~ /\@/ | |
| 181 | + | |
| 182 | + result = profile.members_like field, params[:filter_name] | |
| 183 | + result = result.select{|member| member.can_view_field?(current_person, "email") } if field=="email" | |
| 184 | + render :json => result.map { |member| {:label => "#{member.name}#{member.can_view_field?(current_person, "email") ? " <#{member.email}>" : ""}", :value => member.name }} | |
| 185 | + end | |
| 186 | + | |
| 159 | 187 | end | ... | ... |
app/controllers/public/account_controller.rb
| ... | ... | @@ -198,7 +198,7 @@ class AccountController < ApplicationController |
| 198 | 198 | if request.post? |
| 199 | 199 | begin |
| 200 | 200 | unless verify_recaptcha |
| 201 | - @change_password.errors.add(:base, _('Please type the words correctly')) | |
| 201 | + @change_password.errors.add(:base, _('Please type the captcha text correctly')) | |
| 202 | 202 | return false |
| 203 | 203 | end |
| 204 | 204 | ... | ... |
app/controllers/public/content_viewer_controller.rb
| ... | ... | @@ -68,11 +68,7 @@ class ContentViewerController < ApplicationController |
| 68 | 68 | process_comments(params) |
| 69 | 69 | |
| 70 | 70 | if request.xhr? and params[:comment_order] |
| 71 | - if @comment_order == 'newest' | |
| 72 | - @comments = @comments.reverse | |
| 73 | - end | |
| 74 | - | |
| 75 | - return render :partial => 'comment/comment', :collection => @comments | |
| 71 | + return render :partial => 'comment/comments_with_pagination' | |
| 76 | 72 | end |
| 77 | 73 | |
| 78 | 74 | if params[:slideshow] |
| ... | ... | @@ -209,8 +205,6 @@ class ContentViewerController < ApplicationController |
| 209 | 205 | |
| 210 | 206 | def rendered_file_download(view = nil) |
| 211 | 207 | if @page.download? view |
| 212 | - headers['Content-Type'] = @page.mime_type | |
| 213 | - headers.merge! @page.download_headers | |
| 214 | 208 | data = @page.data |
| 215 | 209 | |
| 216 | 210 | # TODO test the condition |
| ... | ... | @@ -218,7 +212,12 @@ class ContentViewerController < ApplicationController |
| 218 | 212 | raise "No data for file" |
| 219 | 213 | end |
| 220 | 214 | |
| 221 | - render :text => data, :layout => false | |
| 215 | + if @page.published && @page.uploaded_file? | |
| 216 | + redirect_to @page.public_filename | |
| 217 | + else | |
| 218 | + send_data data, @page.download_headers | |
| 219 | + end | |
| 220 | + | |
| 222 | 221 | return true |
| 223 | 222 | end |
| 224 | 223 | |
| ... | ... | @@ -244,8 +243,12 @@ class ContentViewerController < ApplicationController |
| 244 | 243 | |
| 245 | 244 | def get_posts(year = nil, month = nil) |
| 246 | 245 | if year && month |
| 247 | - filter_date = DateTime.parse("#{year}-#{month}-01") | |
| 248 | - return @page.posts.by_range(filter_date..filter_date.at_end_of_month) | |
| 246 | + begin | |
| 247 | + filter_date = DateTime.parse("#{year}-#{month}-01") | |
| 248 | + return @page.posts.by_range(filter_date..filter_date.at_end_of_month) | |
| 249 | + rescue ArgumentError | |
| 250 | + return @page.posts | |
| 251 | + end | |
| 249 | 252 | else |
| 250 | 253 | return @page.posts |
| 251 | 254 | end |
| ... | ... | @@ -276,8 +279,12 @@ class ContentViewerController < ApplicationController |
| 276 | 279 | @comments = @page.comments.without_spam |
| 277 | 280 | @comments = @plugins.filter(:unavailable_comments, @comments) |
| 278 | 281 | @comments_count = @comments.count |
| 279 | - @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] ) | |
| 280 | 282 | @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order] |
| 283 | + @comments = @comments.without_reply | |
| 284 | + if @comment_order == 'newest' | |
| 285 | + @comments = @comments.reverse | |
| 286 | + end | |
| 287 | + @comments = @comments.paginate(:per_page => per_page, :page => params[:comment_page] ) | |
| 281 | 288 | end |
| 282 | 289 | |
| 283 | 290 | private | ... | ... |
app/controllers/public/profile_controller.rb
| ... | ... | @@ -155,6 +155,18 @@ class ProfileController < PublicController |
| 155 | 155 | end |
| 156 | 156 | end |
| 157 | 157 | |
| 158 | + def follow_article | |
| 159 | + article = profile.environment.articles.find params[:article_id] | |
| 160 | + article.person_followers << user | |
| 161 | + redirect_to article.url | |
| 162 | + end | |
| 163 | + | |
| 164 | + def unfollow_article | |
| 165 | + article = profile.environment.articles.find params[:article_id] | |
| 166 | + article.person_followers.delete(user) | |
| 167 | + redirect_to article.url | |
| 168 | + end | |
| 169 | + | |
| 158 | 170 | def unblock |
| 159 | 171 | if current_user.person.is_admin?(profile.environment) |
| 160 | 172 | profile.unblock |
| ... | ... | @@ -362,6 +374,7 @@ class ProfileController < PublicController |
| 362 | 374 | def send_mail |
| 363 | 375 | @mailing = profile.mailings.build(params[:mailing]) |
| 364 | 376 | @email_templates = profile.email_templates.find_all_by_template_type(:organization_members) |
| 377 | + @mailing.data = session[:members_filtered] ? {:members_filtered => session[:members_filtered]} : {} | |
| 365 | 378 | if request.post? |
| 366 | 379 | @mailing.locale = locale |
| 367 | 380 | @mailing.person = user | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -150,14 +150,8 @@ module ApplicationHelper |
| 150 | 150 | link_to text, profile_path(:profile => profile) , options |
| 151 | 151 | end |
| 152 | 152 | |
| 153 | - def link_to_homepage(text, profile = nil, options = {}) | |
| 154 | - p = if profile | |
| 155 | - Profile[profile] | |
| 156 | - else | |
| 157 | - user | |
| 158 | - end | |
| 159 | - | |
| 160 | - link_to text, p.url, options | |
| 153 | + def link_to_homepage(text, profile, options = {}) | |
| 154 | + link_to text, profile.url, options | |
| 161 | 155 | end |
| 162 | 156 | |
| 163 | 157 | def link_if_permitted(link, permission = nil, target = nil) |
| ... | ... | @@ -556,14 +550,25 @@ module ApplicationHelper |
| 556 | 550 | trigger_class = 'enterprise-trigger' |
| 557 | 551 | end |
| 558 | 552 | end |
| 559 | - extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) | |
| 553 | + | |
| 554 | + extra_info_tag = '' | |
| 555 | + img_class = 'profile-image' | |
| 556 | + | |
| 557 | + if extra_info.is_a? Hash | |
| 558 | + extra_info_tag = content_tag( 'span', extra_info[:value], :class => 'extra_info '+extra_info[:class]) | |
| 559 | + img_class +=' '+extra_info[:class] | |
| 560 | + else | |
| 561 | + extra_info_tag = content_tag( 'span', extra_info, :class => 'extra_info' ) | |
| 562 | + end | |
| 563 | + | |
| 560 | 564 | links = links_for_balloon(profile) |
| 561 | 565 | content_tag('div', content_tag(tag, |
| 562 | - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") + | |
| 566 | + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? | |
| 567 | + popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") + | |
| 563 | 568 | link_to( |
| 564 | - content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | |
| 569 | + content_tag( 'span', profile_image( profile, size ), :class => img_class ) + | |
| 565 | 570 | content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + |
| 566 | - extra_info + profile_sex_icon( profile ), | |
| 571 | + extra_info_tag + profile_sex_icon( profile ), | |
| 567 | 572 | profile.url, |
| 568 | 573 | :class => 'profile_link url', |
| 569 | 574 | :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, |
| ... | ... | @@ -711,7 +716,7 @@ module ApplicationHelper |
| 711 | 716 | class NoosferoFormBuilder < ActionView::Helpers::FormBuilder |
| 712 | 717 | extend ActionView::Helpers::TagHelper |
| 713 | 718 | |
| 714 | - def self.output_field(text, field_html, field_id = nil, options = {}) | |
| 719 | + def self.output_field(text, field_html, field_id = nil) | |
| 715 | 720 | # try to guess an id if none given |
| 716 | 721 | if field_id.nil? |
| 717 | 722 | field_html =~ /id=['"]([^'"]*)['"]/ |
| ... | ... | @@ -1040,10 +1045,11 @@ module ApplicationHelper |
| 1040 | 1045 | end |
| 1041 | 1046 | |
| 1042 | 1047 | def search_contents_menu |
| 1048 | + host = environment.default_hostname | |
| 1043 | 1049 | links = [ |
| 1044 | - {s_('contents|More recent') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_recent'})}}, | |
| 1045 | - {s_('contents|More viewed') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_popular'})}}, | |
| 1046 | - {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}} | |
| 1050 | + {s_('contents|More recent') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_recent'})}}, | |
| 1051 | + {s_('contents|More viewed') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_popular'})}}, | |
| 1052 | + {s_('contents|Most commented') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_comments'})}} | |
| 1047 | 1053 | ] |
| 1048 | 1054 | if logged_in? |
| 1049 | 1055 | links.push(_('New content') => modal_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})})) |
| ... | ... | @@ -1055,10 +1061,11 @@ module ApplicationHelper |
| 1055 | 1061 | alias :browse_contents_menu :search_contents_menu |
| 1056 | 1062 | |
| 1057 | 1063 | def search_people_menu |
| 1064 | + host = environment.default_hostname | |
| 1058 | 1065 | links = [ |
| 1059 | - {s_('people|More recent') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_recent'})}}, | |
| 1060 | - {s_('people|More active') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_active'})}}, | |
| 1061 | - {s_('people|More popular') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_popular'})}} | |
| 1066 | + {s_('people|More recent') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_recent'})}}, | |
| 1067 | + {s_('people|More active') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_active'})}}, | |
| 1068 | + {s_('people|More popular') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_popular'})}} | |
| 1062 | 1069 | ] |
| 1063 | 1070 | if logged_in? |
| 1064 | 1071 | links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})}) |
| ... | ... | @@ -1071,10 +1078,11 @@ module ApplicationHelper |
| 1071 | 1078 | alias :browse_people_menu :search_people_menu |
| 1072 | 1079 | |
| 1073 | 1080 | def search_communities_menu |
| 1081 | + host = environment.default_hostname | |
| 1074 | 1082 | links = [ |
| 1075 | - {s_('communities|More recent') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_recent'})}}, | |
| 1076 | - {s_('communities|More active') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_active'})}}, | |
| 1077 | - {s_('communities|More popular') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_popular'})}} | |
| 1083 | + {s_('communities|More recent') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_recent'})}}, | |
| 1084 | + {s_('communities|More active') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_active'})}}, | |
| 1085 | + {s_('communities|More popular') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_popular'})}} | |
| 1078 | 1086 | ] |
| 1079 | 1087 | if logged_in? |
| 1080 | 1088 | links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})}) | ... | ... |
app/helpers/article_helper.rb
| ... | ... | @@ -169,4 +169,30 @@ module ArticleHelper |
| 169 | 169 | _('Edit') |
| 170 | 170 | end |
| 171 | 171 | |
| 172 | + def follow_button_text(article) | |
| 173 | + if article.event? | |
| 174 | + _('Attend') | |
| 175 | + else | |
| 176 | + _('Follow') | |
| 177 | + end | |
| 178 | + end | |
| 179 | + | |
| 180 | + def unfollow_button_text(article) | |
| 181 | + if article.event? | |
| 182 | + _('Unattend') | |
| 183 | + else | |
| 184 | + _('Unfollow') | |
| 185 | + end | |
| 186 | + end | |
| 187 | + | |
| 188 | + def following_button(page, user) | |
| 189 | + if !user.blank? and user != page.author | |
| 190 | + if page.is_followed_by? user | |
| 191 | + button :cancel, unfollow_button_text(page), {:controller => 'profile', :action => 'unfollow_article', :article_id => page.id} | |
| 192 | + else | |
| 193 | + button :add, follow_button_text(page), {:controller => 'profile', :action => 'follow_article', :article_id => page.id} | |
| 194 | + end | |
| 195 | + end | |
| 196 | + end | |
| 197 | + | |
| 172 | 198 | end | ... | ... |
app/helpers/block_helper.rb
| ... | ... | @@ -14,6 +14,7 @@ module BlockHelper |
| 14 | 14 | </td> |
| 15 | 15 | <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> |
| 16 | 16 | <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td> |
| 17 | + <td>#{check_box_tag 'block[images][][new_window]', '1', image[:new_window], :class => 'highlight-new_window', :size => 1}</td> | |
| 17 | 18 | </tr><tr class=\"image-title\" data-row-number='#{row_number}'> |
| 18 | 19 | <td colspan=\"3\"><label>#{ |
| 19 | 20 | content_tag('span', _('Title')) + | ... | ... |
app/helpers/boxes_helper.rb
| ... | ... | @@ -250,7 +250,7 @@ module BoxesHelper |
| 250 | 250 | end |
| 251 | 251 | end |
| 252 | 252 | |
| 253 | - if editable?(block) | |
| 253 | + if editable?(block, user) | |
| 254 | 254 | buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) |
| 255 | 255 | end |
| 256 | 256 | |
| ... | ... | @@ -296,7 +296,7 @@ module BoxesHelper |
| 296 | 296 | return block.movable? || user.is_admin? |
| 297 | 297 | end |
| 298 | 298 | |
| 299 | - def editable?(block) | |
| 300 | - return block.editable? || user.is_admin? | |
| 299 | + def editable?(block, user=nil) | |
| 300 | + return block.editable?(user) || user.is_admin? | |
| 301 | 301 | end |
| 302 | 302 | end | ... | ... |
app/helpers/forms_helper.rb
| ... | ... | @@ -7,9 +7,10 @@ module FormsHelper |
| 7 | 7 | |
| 8 | 8 | def labelled_check_box( human_name, name, value = "1", checked = false, options = {} ) |
| 9 | 9 | options[:id] ||= 'checkbox-' + FormsHelper.next_id_number |
| 10 | - hidden_field_tag(name, '0') + | |
| 11 | - check_box_tag( name, value, checked, options ) + | |
| 12 | - content_tag( 'label', human_name, :for => options[:id] ) | |
| 10 | + html = options[:add_hidden] == false ? "" : hidden_field_tag(name, '0') | |
| 11 | + | |
| 12 | + html += check_box_tag( name, value, checked, options ) + | |
| 13 | + content_tag( 'label', human_name, :for => options[:id] ) | |
| 13 | 14 | end |
| 14 | 15 | |
| 15 | 16 | def labelled_text_field( human_name, name, value=nil, options={} ) | ... | ... |
app/mailers/mailing.rb
| ... | ... | @@ -2,7 +2,10 @@ require_dependency 'mailing_job' |
| 2 | 2 | |
| 3 | 3 | class Mailing < ActiveRecord::Base |
| 4 | 4 | |
| 5 | - attr_accessible :subject, :body | |
| 5 | + acts_as_having_settings :field => :data | |
| 6 | + | |
| 7 | + attr_accessible :subject, :body, :data | |
| 8 | + | |
| 6 | 9 | validates_presence_of :source_id, :subject, :body |
| 7 | 10 | belongs_to :source, :foreign_key => :source_id, :polymorphic => true |
| 8 | 11 | belongs_to :person | ... | ... |
app/mailers/organization_mailing.rb
| ... | ... | @@ -5,9 +5,17 @@ class OrganizationMailing < Mailing |
| 5 | 5 | end |
| 6 | 6 | |
| 7 | 7 | def recipients(offset=0, limit=100) |
| 8 | - source.members.order(:id).offset(offset).limit(limit) | |
| 9 | - .joins("LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)") | |
| 8 | + result = source.members.order(:id).offset(offset).limit(limit) | |
| 9 | + | |
| 10 | + if data.present? and data.is_a?(Hash) and data[:members_filtered] | |
| 11 | + result = result.where('profiles.id IN (?)', data[:members_filtered]) | |
| 12 | + end | |
| 13 | + | |
| 14 | + if result.blank? | |
| 15 | + result = result.joins("LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)") | |
| 10 | 16 | .where("m.person_id" => nil) |
| 17 | + end | |
| 18 | + result | |
| 11 | 19 | end |
| 12 | 20 | |
| 13 | 21 | def each_recipient | ... | ... |
app/models/article.rb
| ... | ... | @@ -8,8 +8,9 @@ class Article < ActiveRecord::Base |
| 8 | 8 | :accept_comments, :feed, :published, :source, :source_name, |
| 9 | 9 | :highlighted, :notify_comments, :display_hits, :slug, |
| 10 | 10 | :external_feed_builder, :display_versions, :external_link, |
| 11 | - :author, :published_at, :person_followers, :show_to_followers, | |
| 12 | - :image_builder, :display_preview, :archived | |
| 11 | + :image_builder, :show_to_followers, | |
| 12 | + :author, :display_preview, :published_at, :person_followers, | |
| 13 | + :archived | |
| 13 | 14 | |
| 14 | 15 | acts_as_having_image |
| 15 | 16 | |
| ... | ... | @@ -83,6 +84,10 @@ class Article < ActiveRecord::Base |
| 83 | 84 | |
| 84 | 85 | has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' |
| 85 | 86 | |
| 87 | + has_many :article_followers, :dependent => :destroy | |
| 88 | + has_many :person_followers, :class_name => 'Person', :through => :article_followers, :source => :person | |
| 89 | + has_many :person_followers_emails, :class_name => 'User', :through => :person_followers, :source => :user, :select => :email | |
| 90 | + | |
| 86 | 91 | has_many :article_categorizations, -> { where 'articles_categories.virtual = ?', false } |
| 87 | 92 | has_many :categories, :through => :article_categorizations |
| 88 | 93 | |
| ... | ... | @@ -95,7 +100,6 @@ class Article < ActiveRecord::Base |
| 95 | 100 | settings_items :author_name, :type => :string, :default => "" |
| 96 | 101 | settings_items :allow_members_to_edit, :type => :boolean, :default => false |
| 97 | 102 | settings_items :moderate_comments, :type => :boolean, :default => false |
| 98 | - settings_items :followers, :type => Array, :default => [] | |
| 99 | 103 | has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' |
| 100 | 104 | |
| 101 | 105 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' |
| ... | ... | @@ -173,7 +177,6 @@ class Article < ActiveRecord::Base |
| 173 | 177 | end |
| 174 | 178 | end |
| 175 | 179 | |
| 176 | - | |
| 177 | 180 | def is_trackable? |
| 178 | 181 | self.published? && self.notifiable? && self.advertise? && self.profile.public_profile |
| 179 | 182 | end |
| ... | ... | @@ -374,6 +377,10 @@ class Article < ActiveRecord::Base |
| 374 | 377 | self.parent and self.parent.forum? |
| 375 | 378 | end |
| 376 | 379 | |
| 380 | + def person_followers_email_list | |
| 381 | + person_followers_emails.map{|p|p.email} | |
| 382 | + end | |
| 383 | + | |
| 377 | 384 | def info_from_last_update |
| 378 | 385 | last_comment = comments.last |
| 379 | 386 | if last_comment |
| ... | ... | @@ -383,6 +390,10 @@ class Article < ActiveRecord::Base |
| 383 | 390 | end |
| 384 | 391 | end |
| 385 | 392 | |
| 393 | + def full_path | |
| 394 | + profile.hostname.blank? ? "/#{profile.identifier}/#{path}" : "/#{path}" | |
| 395 | + end | |
| 396 | + | |
| 386 | 397 | def url |
| 387 | 398 | @url ||= self.profile.url.merge(:page => path.split('/')) |
| 388 | 399 | end |
| ... | ... | @@ -408,13 +419,19 @@ class Article < ActiveRecord::Base |
| 408 | 419 | end |
| 409 | 420 | |
| 410 | 421 | def download? view = nil |
| 411 | - (self.uploaded_file? and not self.image?) or | |
| 412 | - (self.image? and view.blank?) or | |
| 413 | - (not self.uploaded_file? and self.mime_type != 'text/html') | |
| 422 | + false | |
| 423 | + end | |
| 424 | + | |
| 425 | + def is_followed_by?(user) | |
| 426 | + self.person_followers.include? user | |
| 427 | + end | |
| 428 | + | |
| 429 | + def download_disposition | |
| 430 | + 'inline' | |
| 414 | 431 | end |
| 415 | 432 | |
| 416 | 433 | def download_headers |
| 417 | - {} | |
| 434 | + { :filename => filename, :type => mime_type, :disposition => download_disposition} | |
| 418 | 435 | end |
| 419 | 436 | |
| 420 | 437 | def alternate_languages | ... | ... |
app/models/block.rb
| ... | ... | @@ -195,8 +195,8 @@ class Block < ActiveRecord::Base |
| 195 | 195 | nil |
| 196 | 196 | end |
| 197 | 197 | |
| 198 | - # Is this block editable? (Default to <tt>false</tt>) | |
| 199 | - def editable? | |
| 198 | + # Is this block editable? (Default to <tt>true</tt>) | |
| 199 | + def editable?(user=nil) | |
| 200 | 200 | self.edit_modes == "all" |
| 201 | 201 | end |
| 202 | 202 | ... | ... |
app/models/comment.rb
| ... | ... | @@ -6,13 +6,14 @@ class Comment < ActiveRecord::Base |
| 6 | 6 | :body => {:label => _('Content'), :weight => 2}, |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | - attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source | |
| 9 | + attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source, :follow_article | |
| 10 | 10 | |
| 11 | 11 | validates_presence_of :body |
| 12 | 12 | |
| 13 | 13 | belongs_to :source, :counter_cache => true, :polymorphic => true |
| 14 | 14 | alias :article :source |
| 15 | 15 | alias :article= :source= |
| 16 | + attr_accessor :follow_article | |
| 16 | 17 | |
| 17 | 18 | belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' |
| 18 | 19 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
| ... | ... | @@ -102,10 +103,9 @@ class Comment < ActiveRecord::Base |
| 102 | 103 | |
| 103 | 104 | after_create :new_follower |
| 104 | 105 | def new_follower |
| 105 | - if source.kind_of?(Article) | |
| 106 | - article.followers += [author_email] | |
| 107 | - article.followers -= article.profile.notification_emails | |
| 108 | - article.followers.uniq! | |
| 106 | + if source.kind_of?(Article) and !author.nil? and @follow_article | |
| 107 | + article.person_followers += [author] | |
| 108 | + article.person_followers.uniq! | |
| 109 | 109 | article.save |
| 110 | 110 | end |
| 111 | 111 | end |
| ... | ... | @@ -147,7 +147,7 @@ class Comment < ActiveRecord::Base |
| 147 | 147 | if !notification_emails.empty? |
| 148 | 148 | CommentNotifier.notification(self).deliver |
| 149 | 149 | end |
| 150 | - emails = article.followers - [author_email] | |
| 150 | + emails = article.person_followers_email_list - [author_email] | |
| 151 | 151 | if !emails.empty? |
| 152 | 152 | CommentNotifier.mail_to_followers(self, emails).deliver |
| 153 | 153 | end | ... | ... |
app/models/disabled_enterprise_message_block.rb
app/models/environment.rb
| ... | ... | @@ -56,6 +56,7 @@ class Environment < ActiveRecord::Base |
| 56 | 56 | 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), |
| 57 | 57 | 'edit_appearance' => N_('Edit appearance'), |
| 58 | 58 | 'manage_email_templates' => N_('Manage Email Templates'), |
| 59 | + 'edit_raw_html_block' => N_('Edit Raw HTML block'), | |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | 62 | module Roles | ... | ... |
app/models/highlights_block.rb
| ... | ... | @@ -15,6 +15,8 @@ class HighlightsBlock < Block |
| 15 | 15 | if !Noosfero.root.nil? and !i[:address].start_with?(Noosfero.root + '/') |
| 16 | 16 | i[:address] = Noosfero.root + i[:address] |
| 17 | 17 | end |
| 18 | + i[:new_window] = i[:new_window] == '1' ? true : false | |
| 19 | + | |
| 18 | 20 | begin |
| 19 | 21 | file = UploadedFile.find(i[:image_id]) |
| 20 | 22 | i[:image_src] = file.public_filename | ... | ... |
app/models/person.rb
| 1 | 1 | # A person is the profile of an user holding all relationships with the rest of the system |
| 2 | 2 | class Person < Profile |
| 3 | 3 | |
| 4 | - attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, | |
| 5 | - :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, | |
| 6 | - :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, | |
| 7 | - :custom_area_of_study, :professional_activity, :organization_website, :following_articles | |
| 4 | + attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website, :following_articles | |
| 8 | 5 | |
| 9 | 6 | SEARCH_FILTERS = { |
| 10 | 7 | :order => %w[more_recent more_popular more_active], |
| ... | ... | @@ -19,26 +16,29 @@ class Person < Profile |
| 19 | 16 | acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} |
| 20 | 17 | acts_as_accessor |
| 21 | 18 | |
| 22 | - scope :members_of, -> resources { | |
| 19 | + scope :members_of, lambda { |resources, field = ''| | |
| 23 | 20 | resources = Array(resources) |
| 21 | + joins = [:role_assignments] | |
| 22 | + joins << :user if User.attribute_names.include? field | |
| 23 | + | |
| 24 | 24 | conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') |
| 25 | - select('DISTINCT profiles.*').joins(:role_assignments).where([conditions]) | |
| 25 | + distinct.select('profiles.*').joins(joins).where([conditions]) | |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | scope :not_members_of, -> resources { |
| 29 | 29 | resources = Array(resources) |
| 30 | 30 | conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') |
| 31 | - select('DISTINCT profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "role_assignments" ON "role_assignments"."accessor_id" = "profiles"."id" AND "role_assignments"."accessor_type" = (Profile) WHERE "profiles"."type" IN (Person) AND (%s))' % conditions) | |
| 31 | + distinct.select('profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "role_assignments" ON "role_assignments"."accessor_id" = "profiles"."id" AND "role_assignments"."accessor_type" = (Profile) WHERE "profiles"."type" IN (Person) AND (%s))' % conditions) | |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | scope :by_role, -> roles { |
| 35 | 35 | roles = Array(roles) |
| 36 | - select('DISTINCT profiles.*').joins(:role_assignments).where('role_assignments.role_id IN (?)', roles) | |
| 36 | + distinct.select('profiles.*').joins(:role_assignments).where('role_assignments.role_id IN (?)', roles) | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | scope :not_friends_of, -> resources { |
| 40 | 40 | resources = Array(resources) |
| 41 | - select('DISTINCT profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "friendships" ON "friendships"."person_id" = "profiles"."id" WHERE "friendships"."friend_id" IN (%s))' % resources.map(&:id)) | |
| 41 | + distinct.select('profiles.*').where('"profiles"."id" NOT IN (SELECT DISTINCT profiles.id FROM "profiles" INNER JOIN "friendships" ON "friendships"."person_id" = "profiles"."id" WHERE "friendships"."friend_id" IN (%s))' % resources.map(&:id)) | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | scope :visible_for_person, lambda { |person| |
| ... | ... | @@ -51,8 +51,7 @@ class Person < Profile |
| 51 | 51 | ['( roles.key = ? AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR ( |
| 52 | 52 | ( ( friendships.person_id = ? ) OR (profiles.public_profile = ?)) AND (profiles.visible = ?) )', 'environment_administrator', Profile.name, person.id, person.id, true, true] |
| 53 | 53 | ).uniq |
| 54 | - } | |
| 55 | - | |
| 54 | + } | |
| 56 | 55 | |
| 57 | 56 | def has_permission_with_admin?(permission, resource) |
| 58 | 57 | return true if resource.blank? || resource.admins.include?(self) |
| ... | ... | @@ -90,7 +89,8 @@ class Person < Profile |
| 90 | 89 | has_many :article_followers, :dependent => :destroy |
| 91 | 90 | has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article |
| 92 | 91 | has_many :comments, :foreign_key => :author_id |
| 93 | - | |
| 92 | + has_many :article_followers, :dependent => :destroy | |
| 93 | + has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article | |
| 94 | 94 | has_many :friendships, :dependent => :destroy |
| 95 | 95 | has_many :friends, :class_name => 'Person', :through => :friendships |
| 96 | 96 | |
| ... | ... | @@ -123,10 +123,10 @@ class Person < Profile |
| 123 | 123 | scope :more_popular, -> { order 'friends_count DESC' } |
| 124 | 124 | |
| 125 | 125 | scope :abusers, -> { |
| 126 | - joins(:abuse_complaints).where('tasks.status = 3').select('DISTINCT profiles.*') | |
| 126 | + joins(:abuse_complaints).where('tasks.status = 3').distinct.select('profiles.*') | |
| 127 | 127 | } |
| 128 | 128 | scope :non_abusers, -> { |
| 129 | - select("DISTINCT profiles.*"). | |
| 129 | + distinct.select("profiles.*"). | |
| 130 | 130 | joins("LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'"). |
| 131 | 131 | where("tasks.status != 3 OR tasks.id is NULL") |
| 132 | 132 | } |
| ... | ... | @@ -135,6 +135,11 @@ class Person < Profile |
| 135 | 135 | scope :activated, -> { joins(:user).where('users.activation_code IS NULL AND users.activated_at IS NOT NULL') } |
| 136 | 136 | scope :deactivated, -> { joins(:user).where('NOT (users.activation_code IS NULL AND users.activated_at IS NOT NULL)') } |
| 137 | 137 | |
| 138 | + scope :with_role, -> role_id { | |
| 139 | + distinct.joins(:role_assignments). | |
| 140 | + where("role_assignments.role_id = #{role_id}") | |
| 141 | + } | |
| 142 | + | |
| 138 | 143 | after_destroy do |person| |
| 139 | 144 | Friendship.where(friend_id: person.id).each{ |friendship| friendship.destroy } |
| 140 | 145 | end | ... | ... |
app/models/profile.rb
| ... | ... | @@ -78,6 +78,9 @@ class Profile < ActiveRecord::Base |
| 78 | 78 | def self.organization_member_roles(env_id) |
| 79 | 79 | all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?} |
| 80 | 80 | end |
| 81 | + def self.organization_custom_roles(env_id, profile_id) | |
| 82 | + all_roles(env_id).where('profile_id = ?', profile_id) | |
| 83 | + end | |
| 81 | 84 | def self.all_roles(env_id) |
| 82 | 85 | Role.where(environment_id: env_id) |
| 83 | 86 | end |
| ... | ... | @@ -119,7 +122,7 @@ class Profile < ActiveRecord::Base |
| 119 | 122 | include Noosfero::Plugin::HotSpot |
| 120 | 123 | |
| 121 | 124 | scope :memberships_of, -> person { |
| 122 | - select('DISTINCT profiles.*'). | |
| 125 | + distinct.select('profiles.*'). | |
| 123 | 126 | joins(:role_assignments). |
| 124 | 127 | where('role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id) |
| 125 | 128 | } |
| ... | ... | @@ -185,15 +188,23 @@ class Profile < ActiveRecord::Base |
| 185 | 188 | |
| 186 | 189 | include TimeScopes |
| 187 | 190 | |
| 188 | - def members | |
| 191 | + def members(by_field = '') | |
| 189 | 192 | scopes = plugins.dispatch_scopes(:organization_members, self) |
| 190 | - scopes << Person.members_of(self) | |
| 193 | + scopes << Person.members_of(self,by_field) | |
| 191 | 194 | return scopes.first if scopes.size == 1 |
| 192 | 195 | ScopeTool.union *scopes |
| 193 | 196 | end |
| 194 | 197 | |
| 195 | - def members_by_name | |
| 196 | - members.order('profiles.name') | |
| 198 | + def members_by(field,value = nil) | |
| 199 | + if value and !value.blank? | |
| 200 | + members_like(field,value).order('profiles.name') | |
| 201 | + else | |
| 202 | + members.order('profiles.name') | |
| 203 | + end | |
| 204 | + end | |
| 205 | + | |
| 206 | + def members_like(field,value) | |
| 207 | + members(field).where("LOWER(#{field}) LIKE ?", "%#{value.downcase}%") if value | |
| 197 | 208 | end |
| 198 | 209 | |
| 199 | 210 | class << self |
| ... | ... | @@ -781,13 +792,13 @@ private :generate_url, :url_options |
| 781 | 792 | end |
| 782 | 793 | |
| 783 | 794 | # Adds a person as member of this Profile. |
| 784 | - def add_member(person) | |
| 795 | + def add_member(person, attributes={}) | |
| 785 | 796 | if self.has_members? |
| 786 | 797 | if self.closed? && members.count > 0 |
| 787 | 798 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) |
| 788 | 799 | else |
| 789 | - self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0 | |
| 790 | - self.affiliate(person, Profile::Roles.member(environment.id)) | |
| 800 | + self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0 | |
| 801 | + self.affiliate(person, Profile::Roles.member(environment.id), attributes) | |
| 791 | 802 | end |
| 792 | 803 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } |
| 793 | 804 | remove_from_suggestion_list person |
| ... | ... | @@ -1164,6 +1175,10 @@ private :generate_url, :url_options |
| 1164 | 1175 | end |
| 1165 | 1176 | end |
| 1166 | 1177 | |
| 1178 | + def can_view_field? current_person, field | |
| 1179 | + display_private_info_to?(current_person) || (public_fields.include?(field) && public?) | |
| 1180 | + end | |
| 1181 | + | |
| 1167 | 1182 | validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true |
| 1168 | 1183 | def preferred_login_redirection |
| 1169 | 1184 | redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login | ... | ... |
app/models/raw_html_block.rb
app/models/rss_feed.rb
app/models/uploaded_file.rb
| ... | ... | @@ -2,6 +2,9 @@ |
| 2 | 2 | # |
| 3 | 3 | # Limitation: only file metadata are versioned. Only the latest version |
| 4 | 4 | # of the file itself is kept. (FIXME?) |
| 5 | + | |
| 6 | +require 'sdbm' | |
| 7 | + | |
| 5 | 8 | class UploadedFile < Article |
| 6 | 9 | |
| 7 | 10 | attr_accessible :uploaded_data, :title |
| ... | ... | @@ -10,6 +13,19 @@ class UploadedFile < Article |
| 10 | 13 | _('File') |
| 11 | 14 | end |
| 12 | 15 | |
| 16 | + DBM_PRIVATE_FILE = 'cache/private_files' | |
| 17 | + after_save do |uploaded_file| | |
| 18 | + if uploaded_file.published_changed? | |
| 19 | + dbm = SDBM.open(DBM_PRIVATE_FILE) | |
| 20 | + if uploaded_file.published | |
| 21 | + dbm.delete(uploaded_file.public_filename) | |
| 22 | + else | |
| 23 | + dbm.store(uploaded_file.public_filename, uploaded_file.full_path) | |
| 24 | + end | |
| 25 | + dbm.close | |
| 26 | + end | |
| 27 | + end | |
| 28 | + | |
| 13 | 29 | track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :parent |
| 14 | 30 | |
| 15 | 31 | def title |
| ... | ... | @@ -106,10 +122,13 @@ class UploadedFile < Article |
| 106 | 122 | self.name ||= self.filename |
| 107 | 123 | end |
| 108 | 124 | |
| 109 | - def download_headers | |
| 110 | - { | |
| 111 | - 'Content-Disposition' => "attachment; filename=\"#{self.filename}\"", | |
| 112 | - } | |
| 125 | + def download_disposition | |
| 126 | + case content_type | |
| 127 | + when 'application/pdf' | |
| 128 | + 'inline' | |
| 129 | + else | |
| 130 | + 'attachment' | |
| 131 | + end | |
| 113 | 132 | end |
| 114 | 133 | |
| 115 | 134 | def data | ... | ... |
app/views/account/forgot_password.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <%= form_tag({:action => 'forgot_password'}, :method => 'post', :id => 'forgot-password-form') do %> |
| 6 | 6 | <%= labelled_form_field fields_label, text_field_tag(:value) %> |
| 7 | 7 | |
| 8 | - <h3><%= _('Please type the two words below') %></h3> | |
| 8 | + <h3><%= _('Please type the captcha text below') %></h3> | |
| 9 | 9 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> |
| 10 | 10 | |
| 11 | 11 | <div> | ... | ... |
app/views/account/index.html.erb
app/views/blocks/highlights.html.erb
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | <div class='highlights-border'> |
| 4 | 4 | <div class='highlights-container'> |
| 5 | 5 | <% block.featured_images.each do |img| %> |
| 6 | - <a href="<%= img[:address] %>" title="<%= img[:title] %>" class="highlights-image-link"> | |
| 6 | + <a href="<%= img[:address] %>" <%= 'target="_blank"' if img[:new_window] %> title="<%= img[:title] %>" class="highlights-image-link"> | |
| 7 | 7 | <%= image_tag [Noosfero.root, img[:image_src]].join, alt: img[:title] %> |
| 8 | 8 | <p class="highlights-label"><%= img[:title] %></p> |
| 9 | 9 | </a> | ... | ... |
app/views/box_organizer/_highlights_block.html.erb
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | <strong><%= _('Highlights') %></strong> |
| 4 | 4 | |
| 5 | 5 | <table class="noborder"><tbody id="highlights-data-table"> |
| 6 | - <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th></tr> | |
| 6 | + <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('New Window') %></th></tr> | |
| 7 | 7 | <% @block.images.each_with_index do |image, index| %> |
| 8 | 8 | <%= highlights_block_config_image_fields @block, image, index %> |
| 9 | 9 | <% end %> | ... | ... |
app/views/cms/_drag_and_drop_note.html.erb
app/views/cms/_text_editor_sidebar.html.erb
| ... | ... | @@ -17,8 +17,8 @@ |
| 17 | 17 | :parent_id, profile, default_folder, {}, {}, |
| 18 | 18 | "type='Folder' or type='Gallery'" |
| 19 | 19 | ) %> |
| 20 | + <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %> | |
| 20 | 21 | </div> |
| 21 | - <%= button(:newfolder, _('New folder'), '#', :id => 'new-folder-button') %> | |
| 22 | 22 | <p><%= file_field_tag('file', :multiple => true) %></p> |
| 23 | 23 | <% end %> |
| 24 | 24 | </div> |
| ... | ... | @@ -31,7 +31,7 @@ |
| 31 | 31 | <div id='published-media' class='text-editor-sidebar-box' data-url='<%= url_for({:controller => 'cms', :action => 'published_media_items', :profile => profile.identifier}) %>'> |
| 32 | 32 | <%= select_profile_folder(nil, :parent_id, profile, 'recent-media', {}, {}, |
| 33 | 33 | "type='Folder' or type='Gallery'", {:root_label => _('Recent media')}) %> |
| 34 | - <%= labelled_form_field _('Search'), text_field_tag('q') %> | |
| 34 | + <%= labelled_form_field _('Search among your uploaded files'), text_field_tag('q', '', placeholder: _('Write words about the file you are looking for')) %> | |
| 35 | 35 | <%= render :partial => 'drag_and_drop_note' %> |
| 36 | 36 | <div class='items'> |
| 37 | 37 | <%= render :partial => 'published_media_items' %> | ... | ... |
app/views/comment/_comment_form.html.erb
| ... | ... | @@ -77,6 +77,10 @@ function check_captcha(button, confirm_action) { |
| 77 | 77 | <%= labelled_form_field(_('Title'), f.text_field(:title)) %> |
| 78 | 78 | <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> |
| 79 | 79 | |
| 80 | + <% if logged_in? %> | |
| 81 | + <%= labelled_form_field check_box(:comment, :follow_article, {}, true, false) + _('Follow this article'), '' %> | |
| 82 | + <% end%> | |
| 83 | + | |
| 80 | 84 | <%= hidden_field_tag(:confirm, 'false') %> |
| 81 | 85 | <%= hidden_field_tag(:view, params[:view])%> |
| 82 | 86 | <%= f.hidden_field(:reply_of_id) %> | ... | ... |
app/views/content_viewer/_article_toolbar.html.erb
app/views/content_viewer/_publishing_info.html.erb
| ... | ... | @@ -10,6 +10,24 @@ |
| 10 | 10 | <%= (" - %s") % link_to_comments(@page)%> |
| 11 | 11 | </span> |
| 12 | 12 | <% end %> |
| 13 | + | |
| 14 | +<span class="followers-count"> | |
| 15 | +| | |
| 16 | +<% if @page.event? %> | |
| 17 | + <% if @page.person_followers.size > 0 %> | |
| 18 | + <%= _("%s will attend this event.") % [ pluralize(@page.person_followers.size, _("person"))]%> | |
| 19 | + <% else %> | |
| 20 | + <%= _("No one attending this event yet.") %> | |
| 21 | + <% end %> | |
| 22 | +<% else %> | |
| 23 | + <% if @page.person_followers.size > 0 %> | |
| 24 | + <%= _("%s following this article.") % [ pluralize(@page.person_followers.size, _("person"))]%> | |
| 25 | + <% else %> | |
| 26 | + <%= _("No one following this article yet.") %> | |
| 27 | + <% end %> | |
| 28 | +<% end %> | |
| 29 | +</span> | |
| 30 | + | |
| 13 | 31 | </span> |
| 14 | 32 | |
| 15 | 33 | <% if @page.display_hits? || @page.license.present? %> | ... | ... |
app/views/content_viewer/view_page.html.erb
| ... | ... | @@ -81,7 +81,7 @@ |
| 81 | 81 | <ul class="article-comments-list"> |
| 82 | 82 | <% if @comments.present? %> |
| 83 | 83 | <%= render :partial => 'comment/comment', :collection => @comments %> |
| 84 | - <%= pagination_links @comments, :param_name => 'comment_page' %> | |
| 84 | + <%= pagination_links @comments, :param_name => 'comment_page', :params => { :comment_order => @comment_order } %> | |
| 85 | 85 | <% end %> |
| 86 | 86 | </ul> |
| 87 | 87 | ... | ... |
app/views/file_presenter/_generic.html.erb
| ... | ... | @@ -2,4 +2,4 @@ |
| 2 | 2 | <%= generic.abstract %> |
| 3 | 3 | </div> |
| 4 | 4 | |
| 5 | -<%= button(:download, _('Download'), [Noosfero.root, generic.public_filename].join, class:'download-link', option:'primary', size:'lg') %> | |
| 5 | +<%= button(:download, _('Download'), generic.url, class:'download-link', option:'primary', size:'lg', :target => "_blank") %> | ... | ... |
app/views/profile/_profile_members_list.html.erb
| ... | ... | @@ -9,7 +9,8 @@ |
| 9 | 9 | </div> |
| 10 | 10 | <ul class="profile-list-<%= role %>" > |
| 11 | 11 | <% users.each do |u| %> |
| 12 | - <%= profile_image_link(u, :thumb) %> | |
| 12 | + <% extra_info = u.member_since_date(profile) == Date.today ? {:value =>_('New'), :class => 'new-profile'}:'' %> | |
| 13 | + <%= profile_image_link(u, :thumb, 'li', extra_info) %> | |
| 13 | 14 | <% end %> |
| 14 | 15 | </ul> |
| 15 | 16 | ... | ... |
app/views/profile/members.html.erb
app/views/profile/send_mail.html.erb
| ... | ... | @@ -10,6 +10,9 @@ |
| 10 | 10 | </div> |
| 11 | 11 | <% end %> |
| 12 | 12 | |
| 13 | + <% to = @mailing.data[:members_filtered].present? ? @mailing.recipients.map{|r| r.name}.join(', ') : _('All members')%> | |
| 14 | + <%= labelled_form_field(_('To:'), text_area(:data, 'members_filtered', :value => to, :rows => 4, :disabled => 'disabled', :class => 'send-mail-recipients')) %> | |
| 15 | + | |
| 13 | 16 | <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> |
| 14 | 17 | |
| 15 | 18 | <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | ... | ... |
app/views/profile_members/_index_buttons.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <%= button :person, _('Invite people to join'), :controller => 'invite', :action => 'invite_friends' %> |
| 6 | 6 | <% end %> |
| 7 | 7 | <% if profile.community? and user.has_permission?(:send_mail_to_members, profile) %> |
| 8 | - <%= button :send, _('Send e-mail to members'), :controller => 'profile', :action => 'send_mail' %> | |
| 8 | + <%= submit_button(:send, _('Send e-mail to members')) %> | |
| 9 | 9 | <% end %> |
| 10 | 10 | <% @plugins.dispatch(:manage_members_extra_buttons).each do |plugin_button| %> |
| 11 | 11 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url] %> | ... | ... |
| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | +<%= form_tag '#', :method => 'post' do %> | |
| 2 | + | |
| 3 | + <%= field_set_tag _('Filter'), :class => 'filter_fields' do %> | |
| 4 | + <p> | |
| 5 | + <%= labelled_text_field(_('Name or Email')+': ', "filters[name]", @filters[:name], {:id => 'filter-name-autocomplete',:size => 30}) %> | |
| 6 | + </p> | |
| 7 | + | |
| 8 | + <p><%= _('Roles:') %> </p> | |
| 9 | + <% @data[:roles].each do |r| %> | |
| 10 | + <%= labelled_check_box(r.name, 'filters[roles][]', r.id, @filters[:roles].include?(r.id.to_s), :add_hidden => false) %><br/> | |
| 11 | + <% end %> | |
| 12 | + <p> | |
| 13 | + <%= submit_button(:search, _('Search')) %> | |
| 14 | + </p> | |
| 15 | + <% end %> | |
| 16 | +<% end %> | |
| 17 | + | |
| 18 | +<%= javascript_include_tag params[:controller] %> | |
| 0 | 19 | \ No newline at end of file | ... | ... |
app/views/profile_members/_members_list.html.erb
| 1 | -<% collection = @collection == :profile_admins ? profile.admins : profile.members_by_name %> | |
| 1 | +<% members = @data ? @data[:members] : profile.members_by('name') %> | |
| 2 | +<% collection = @collection == :profile_admins ? profile.admins : members %> | |
| 2 | 3 | <% title = @title ? @title : _('Current members') %> |
| 3 | 4 | <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %> |
| 5 | +<%= javascript_include_tag params[:controller] %> | |
| 4 | 6 | |
| 5 | 7 | <h3><%= title %></h3> |
| 6 | 8 | |
| 7 | 9 | <table> |
| 10 | + <col width="1"> | |
| 8 | 11 | <tr> |
| 12 | + <th><%= check_box_tag 'checkbox-all', 1, false, :onClick => "toggle(this)" %></th> | |
| 9 | 13 | <th><%= _('Member') %></th> |
| 10 | 14 | <th><%= _('Actions') %></th> |
| 11 | 15 | </tr> |
| 16 | + | |
| 12 | 17 | <% collection.each do |m| %> |
| 13 | 18 | <tr title="<%= m.name %>"> |
| 19 | + <td><%= labelled_check_box('', 'members_filtered[]', m.id.to_s, false, :id => 'checkbox-'+m.identifier) %></td> | |
| 14 | 20 | <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td> |
| 15 | 21 | <td> |
| 16 | 22 | <div class="members-buttons-cell"> |
| ... | ... | @@ -27,3 +33,8 @@ |
| 27 | 33 | </tr> |
| 28 | 34 | <% end %> |
| 29 | 35 | </table> |
| 36 | +<% if collection.empty? %> | |
| 37 | + <p> | |
| 38 | + <em><%= _('No members found to: %s') % profile.name %></em> | |
| 39 | + </p> | |
| 40 | +<% end %> | ... | ... |
app/views/profile_members/index.html.erb
| 1 | 1 | <h1><%= h profile.short_name(50) %></h1> |
| 2 | 2 | |
| 3 | -<%= render :partial => 'index_buttons' %> | |
| 3 | +<%= render :partial => 'members_filter' %> | |
| 4 | 4 | |
| 5 | -<div id="members-list"> | |
| 6 | - <%= render :partial => 'members_list' %> | |
| 7 | -</div> | |
| 5 | +<%= form_tag 'profile_members/send_mail', :method => 'post' do %> | |
| 6 | + <div id="members-list"> | |
| 7 | + <%= render :partial => 'members_list' %> | |
| 8 | + </div> | |
| 8 | 9 | |
| 9 | -<%= render :partial => 'index_buttons' %> | |
| 10 | + <%= render :partial => 'index_buttons' %> | |
| 11 | + | |
| 12 | +<% end %> | ... | ... |
app/views/region_validators/region.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <ul> |
| 6 | 6 | <% for validator in @region.validators %> |
| 7 | 7 | <li> |
| 8 | - <%= link_to_homepage validator.name, validator.identifier %> | |
| 8 | + <%= link_to_homepage validator.name, validator %> | |
| 9 | 9 | <%= link_to _('Remove validation rights'), { :action => 'remove', :id => @region.id, :validator_id => validator }, :method => 'post' %> |
| 10 | 10 | </li> |
| 11 | 11 | <% end %> | ... | ... |
app/views/search/_full_enterprise.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | @order == 'more_recent' ? enterprise.send(@order + '_label') + show_date(enterprise.created_at) : enterprise.send(@order + '_label') %> |
| 6 | 6 | </div> |
| 7 | 7 | <div class="search-enterprise-item-column-right"> |
| 8 | - <%= link_to_homepage(enterprise.name, enterprise.identifier, :class => "search-result-title") %> | |
| 8 | + <%= link_to_homepage enterprise.name, enterprise, class: "search-result-title" %> | |
| 9 | 9 | <div class="search-enterprise-description"> |
| 10 | 10 | <% if enterprise.description %> |
| 11 | 11 | <% body_stripped = strip_tags(enterprise.description) %> | ... | ... |
app/views/search/_full_product.html.erb
| ... | ... | @@ -44,7 +44,7 @@ |
| 44 | 44 | <div class="search-product-item-second-column"> |
| 45 | 45 | <%= link_to_product product, :class => 'search-result-title' %> |
| 46 | 46 | <div class="search-product-supplier"> |
| 47 | - <span class="search-field-label"><%= _('Supplier') %> </span><%= link_to_homepage(product.enterprise.name, product.enterprise.identifier) %> | |
| 47 | + <span class="search-field-label"><%= _('Supplier') %> </span><%= link_to_homepage product.enterprise.name, product.enterprise %> | |
| 48 | 48 | </div> |
| 49 | 49 | <div class="search-product-description"> |
| 50 | 50 | <% if product.description %> | ... | ... |
app/views/search/_image.html.erb
| ... | ... | @@ -26,7 +26,7 @@ |
| 26 | 26 | <% end %> |
| 27 | 27 | <% elsif image.is_a? Gallery %> |
| 28 | 28 | <div class="search-gallery-items"> |
| 29 | - <% r = image.children.order(:updated_at).where('type = ?', 'UploadedFile').last(3) %> | |
| 29 | + <% r = image.children.latest.images.limit(3) %> | |
| 30 | 30 | <% if r.length > 0 %> |
| 31 | 31 | <% r.each_index do |i| img = r[i] %> |
| 32 | 32 | <%= link_to '', img.view_url, :class => "search-image-pic pic-num#{i+1}", |
| ... | ... | @@ -47,6 +47,8 @@ |
| 47 | 47 | <% else %> |
| 48 | 48 | <div class="search-no-image"><span><%= _('No image') %></span></div> |
| 49 | 49 | <% end %> |
| 50 | + <% elsif image.first_image.present? %> | |
| 51 | + <img src="<%= image.first_image %>" class="automatic-abstract-thumb search-image-pic"> | |
| 50 | 52 | <% else %> |
| 51 | 53 | <div class="search-content-type-icon icon-content-<%=image.class.to_s.underscore.dasherize%>"></div> |
| 52 | 54 | <% end %> | ... | ... |
app/views/user_mailer/activation_code.text.erb
| 1 | 1 | <%= _('Hi, %{recipient}!') % { :recipient => @recipient } %> |
| 2 | 2 | |
| 3 | -<%= word_wrap(_('Welcome to %{environment}! To activate your account, follow the link: %{activation_url}') % { :environment => @environment.name, :activation_url => @url + url_for(:controller => :account, :action => :activate, :activation_code => @activation_code, :redirection => @redirection, :join => @join) }) %> | |
| 3 | +<%= word_wrap(_('Welcome to %{environment}! To activate your account, follow the link: %{activation_url}') % { :environment => @environment.name, :activation_url => url_for(:controller => :account, :action => :activate, :activation_code => @activation_code, :redirection => @redirection, :join => @join) }) %> | |
| 4 | 4 | |
| 5 | 5 | <%= _("Greetings,") %> |
| 6 | 6 | |
| 7 | 7 | -- |
| 8 | 8 | <%= _('%s team.') % @environment.name %> |
| 9 | -<%= url_for @url %> | |
| 9 | +<%= @url %> | ... | ... |
db/migrate/20150103134141_add_edit_raw_html_block_to_admin_role.rb
0 → 100644
| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | +class AddEditRawHtmlBlockToAdminRole < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + Environment.all.map(&:id).each do |id| | |
| 4 | + role = Environment::Roles.admin(id) | |
| 5 | + role.permissions << 'edit_raw_html_block' | |
| 6 | + role.save! | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def self.down | |
| 11 | + Environment.all.map(&:id).each do |id| | |
| 12 | + role = Environment::Roles.admin(id) | |
| 13 | + role.permissions -= ['edit_raw_html_block'] | |
| 14 | + role.save! | |
| 15 | + end | |
| 16 | + end | |
| 17 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class CreateArticleFollowers < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + execute("CREATE TABLE article_followers AS (SELECT profiles.id AS person_id, t.id AS article_id, clock_timestamp() AS since FROM (SELECT articles.id, regexp_split_to_table(replace(replace(substring(articles.setting FROM ':followers:[^:]*'), ':followers:', ''), '- ', ''), '\n') AS follower FROM articles) t INNER JOIN users ON users.email = follower INNER JOIN profiles ON users.id = profiles.user_id WHERE follower != '');") | |
| 4 | + add_timestamps :article_followers | |
| 5 | + add_index :article_followers, :person_id | |
| 6 | + add_index :article_followers, :article_id | |
| 7 | + add_index :article_followers, [:person_id, :article_id], :unique => true | |
| 8 | + end | |
| 9 | + | |
| 10 | + def self.down | |
| 11 | + drop_table :article_followers | |
| 12 | + end | |
| 13 | +end | ... | ... |
db/migrate/20151210230319_add_followers_count_to_article.rb
0 → 100644
| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | +class AddFollowersCountToArticle < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + add_column :articles, :followers_count, :integer, :default => 0 | |
| 4 | + execute "update articles set followers_count = (select count(*) from article_followers where article_followers.article_id = articles.id)" | |
| 5 | + end | |
| 6 | + | |
| 7 | + def self.down | |
| 8 | + remove_column :articles, :followers_count | |
| 9 | + end | |
| 10 | +end | ... | ... |
db/migrate/20160202142247_add_timestamps_to_role_assignments.rb
0 → 100644
db/schema.rb
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | # |
| 12 | 12 | # It's strongly recommended that you check this file into your version control system. |
| 13 | 13 | |
| 14 | -ActiveRecord::Schema.define(version: 20151221105330) do | |
| 14 | +ActiveRecord::Schema.define(version: 20160224132937) do | |
| 15 | 15 | |
| 16 | 16 | # These are extensions that must be enabled in order to support this database |
| 17 | 17 | enable_extension "plpgsql" |
| ... | ... | @@ -88,9 +88,9 @@ ActiveRecord::Schema.define(version: 20151221105330) do |
| 88 | 88 | t.integer "profile_id" |
| 89 | 89 | end |
| 90 | 90 | |
| 91 | - create_table "article_followers", force: :cascade do |t| | |
| 92 | - t.integer "person_id", null: false | |
| 93 | - t.integer "article_id", null: false | |
| 91 | + create_table "article_followers", id: false, force: :cascade do |t| | |
| 92 | + t.integer "person_id" | |
| 93 | + t.integer "article_id" | |
| 94 | 94 | t.datetime "since" |
| 95 | 95 | t.datetime "created_at" |
| 96 | 96 | t.datetime "updated_at" |
| ... | ... | @@ -699,6 +699,7 @@ ActiveRecord::Schema.define(version: 20151221105330) do |
| 699 | 699 | t.string "locale" |
| 700 | 700 | t.datetime "created_at" |
| 701 | 701 | t.datetime "updated_at" |
| 702 | + t.text "data" | |
| 702 | 703 | end |
| 703 | 704 | |
| 704 | 705 | create_table "mark_comment_as_read_plugin", force: :cascade do |t| |
| ... | ... | @@ -1071,12 +1072,14 @@ ActiveRecord::Schema.define(version: 20151221105330) do |
| 1071 | 1072 | end |
| 1072 | 1073 | |
| 1073 | 1074 | create_table "role_assignments", force: :cascade do |t| |
| 1074 | - t.integer "accessor_id", null: false | |
| 1075 | - t.string "accessor_type" | |
| 1076 | - t.integer "resource_id" | |
| 1077 | - t.string "resource_type" | |
| 1078 | - t.integer "role_id", null: false | |
| 1079 | - t.boolean "is_global" | |
| 1075 | + t.integer "accessor_id", null: false | |
| 1076 | + t.string "accessor_type" | |
| 1077 | + t.integer "resource_id" | |
| 1078 | + t.string "resource_type" | |
| 1079 | + t.integer "role_id", null: false | |
| 1080 | + t.boolean "is_global" | |
| 1081 | + t.datetime "created_at" | |
| 1082 | + t.datetime "updated_at" | |
| 1080 | 1083 | end |
| 1081 | 1084 | |
| 1082 | 1085 | create_table "roles", force: :cascade do |t| | ... | ... |
debian/apache2/virtualhost.conf
| ... | ... | @@ -8,6 +8,19 @@ DocumentRoot "/usr/share/noosfero/public" |
| 8 | 8 | |
| 9 | 9 | RewriteEngine On |
| 10 | 10 | |
| 11 | +# If your XMPP XMPP/BOSH isn't in localhost, change the config below to correct | |
| 12 | +# point to address | |
| 13 | +RewriteRule /http-bind http://localhost:5280/http-bind [P,QSA,L] | |
| 14 | +<Proxy http://localhost:5280/http-bind> | |
| 15 | + Order Allow,Deny | |
| 16 | + Allow from All | |
| 17 | +</Proxy> | |
| 18 | + | |
| 19 | +# Pass access to private files to backend | |
| 20 | +RewriteMap private_files "dbm=sdbm:/usr/share/noosfero/cache/private_files" | |
| 21 | +RewriteCond ${private_files:$1|NOT_FOUND} !NOT_FOUND | |
| 22 | +RewriteRule ^(/articles/.*) ${private_files:$1} [P,QSA,L] | |
| 23 | + | |
| 11 | 24 | # Rewrite index to check for static index.html |
| 12 | 25 | RewriteRule ^/$ /index.html [QSA] |
| 13 | 26 | ... | ... |
debian/changelog
debian/dbinstall
| ... | ... | @@ -5,8 +5,6 @@ set -e |
| 5 | 5 | # dbconfig-common uses "pgsql", but we want "postgresql" |
| 6 | 6 | sed -i -e 's/adapter: pgsql/adapter: postgresql/' /etc/noosfero/database.yml |
| 7 | 7 | |
| 8 | -/etc/init.d/noosfero setup | |
| 9 | - | |
| 10 | 8 | cd /usr/share/noosfero && su noosfero -c "rake db:schema:load RAILS_ENV=production" |
| 11 | 9 | cd /usr/share/noosfero && su noosfero -c "rake db:migrate RAILS_ENV=production SCHEMA=/dev/null" |
| 12 | 10 | cd /usr/share/noosfero && su noosfero -c "rake db:data:minimal RAILS_ENV=production" | ... | ... |
debian/dbupgrade
debian/noosfero.links
| 1 | 1 | var/tmp/noosfero usr/share/noosfero/tmp |
| 2 | 2 | var/log/noosfero usr/share/noosfero/log |
| 3 | +var/cache/noosfero usr/share/noosfero/cache | |
| 3 | 4 | etc/noosfero/database.yml usr/share/noosfero/config/database.yml |
| 4 | 5 | etc/noosfero/unicorn.rb usr/share/noosfero/config/unicorn.rb |
| 5 | 6 | etc/noosfero/plugins usr/share/noosfero/config/plugins | ... | ... |
debian/noosfero.postinst
| ... | ... | @@ -68,10 +68,17 @@ if [ ! -z "$RET" ]; then |
| 68 | 68 | export NOOSFERO_DOMAIN="$RET" |
| 69 | 69 | fi |
| 70 | 70 | |
| 71 | +/etc/init.d/noosfero setup | |
| 72 | + | |
| 71 | 73 | # dbconfig-common magic |
| 72 | 74 | . /usr/share/dbconfig-common/dpkg/postinst |
| 73 | 75 | dbc_go noosfero $@ |
| 74 | 76 | |
| 77 | +if [ ! -f /usr/share/noosfero/cache/private_files.pag ] && [ $1 = "configure" ] && [ -n $2 ]; then | |
| 78 | + echo "Creating private files dbm map..." | |
| 79 | + cd /usr/share/noosfero && su noosfero -c "rake cache:private_files RAILS_ENV=production" | |
| 80 | +fi | |
| 81 | + | |
| 75 | 82 | # stop debconf to avoid the problem with infinite hanging, cfe |
| 76 | 83 | # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=295477 |
| 77 | 84 | db_stop | ... | ... |
debian/update-noosfero-apache
| ... | ... | @@ -17,13 +17,13 @@ if test -x /usr/share/noosfero/script/apacheconf; then |
| 17 | 17 | if ! test -e "$apache_site"; then |
| 18 | 18 | echo "Generating apache virtual host ..." |
| 19 | 19 | cd /usr/share/noosfero && su noosfero -c "RAILS_ENV=production ./script/apacheconf virtualhosts" > "$apache_site" |
| 20 | - else | |
| 21 | - pattern="Include \/etc\/noosfero\/apache\/virtualhost.conf" | |
| 22 | - include="Include \/usr\/share\/noosfero\/util\/chat\/apache\/xmpp.conf" | |
| 23 | - if ! cat $apache_site | grep "^ *$include" > /dev/null ; then | |
| 24 | - echo "Updating apache virtual host ..." | |
| 25 | - sed -i "s/.*$pattern.*/ $include\n&/" $apache_site | |
| 26 | - fi | |
| 20 | + fi | |
| 21 | + | |
| 22 | + # remove old way to include chat config | |
| 23 | + pattern="Include \/usr\/share\/noosfero\/util\/chat\/apache\/xmpp.conf" | |
| 24 | + if cat $apache_site | grep "^ *$pattern" > /dev/null ; then | |
| 25 | + echo "Removing obsolete chat configuration ..." | |
| 26 | + sed -i "/.*$pattern.*/d" $apache_site | |
| 27 | 27 | fi |
| 28 | 28 | |
| 29 | 29 | echo 'Noosfero Apache configuration updated.' | ... | ... |
etc/init.d/noosfero
| ... | ... | @@ -86,6 +86,13 @@ do_setup() { |
| 86 | 86 | chmod 750 /var/tmp/noosfero |
| 87 | 87 | fi |
| 88 | 88 | |
| 89 | + # Noosfero cache directory | |
| 90 | + if [ ! -d /var/cache/noosfero ]; then | |
| 91 | + mkdir /var/cache/noosfero | |
| 92 | + chown $NOOSFERO_USER:root /var/cache/noosfero | |
| 93 | + chmod 755 /var/cache/noosfero | |
| 94 | + fi | |
| 95 | + | |
| 89 | 96 | # symlink the directories into Noosfero directory |
| 90 | 97 | if [ ! -e $NOOSFERO_DIR/tmp ]; then |
| 91 | 98 | ln -s /var/tmp/noosfero $NOOSFERO_DIR/tmp |
| ... | ... | @@ -96,6 +103,9 @@ do_setup() { |
| 96 | 103 | if [ ! -e $NOOSFERO_DIR/log ]; then |
| 97 | 104 | ln -s /var/log/noosfero $NOOSFERO_DIR/log |
| 98 | 105 | fi |
| 106 | + if [ ! -e $NOOSFERO_DIR/cache ]; then | |
| 107 | + ln -s /var/cache/noosfero $NOOSFERO_DIR/cache | |
| 108 | + fi | |
| 99 | 109 | } |
| 100 | 110 | |
| 101 | 111 | do_start() { | ... | ... |
features/admin_categories.feature
| ... | ... | @@ -45,7 +45,7 @@ Feature: manage categories |
| 45 | 45 | And I should see "Steak" |
| 46 | 46 | When I follow "Hide" |
| 47 | 47 | Then I should not see "Vegetarian" |
| 48 | - And "Steak" should not be visible within "div" | |
| 48 | + And I should not see "Steak" | |
| 49 | 49 | |
| 50 | 50 | @selenium |
| 51 | 51 | Scenario: the show link is available just for categories with category tree | ... | ... |
features/categories_block.feature
| ... | ... | @@ -44,6 +44,7 @@ Feature: categories_block |
| 44 | 44 | And I follow "Edit" within ".block-outer .categories-block" |
| 45 | 45 | And I check "Product" |
| 46 | 46 | And I press "Save" |
| 47 | + And I go to / | |
| 47 | 48 | Then I should see "Food" |
| 48 | 49 | And I should see "Book" |
| 49 | 50 | And "Vegetarian" should not be visible within "span#category-name" |
| ... | ... | @@ -62,6 +63,7 @@ Feature: categories_block |
| 62 | 63 | And I follow "Edit" within ".block-outer .categories-block" |
| 63 | 64 | And I check "Product" |
| 64 | 65 | And I press "Save" |
| 66 | + And I go to / | |
| 65 | 67 | Then I should see "Book" |
| 66 | 68 | And "Literature" should not be visible within "span#category-name" |
| 67 | 69 | When I follow "block_2_category_2" | ... | ... |
features/comment.feature
| ... | ... | @@ -96,4 +96,4 @@ Feature: comment |
| 96 | 96 | Scenario: hide post a comment button when clicked |
| 97 | 97 | Given I am on /booking/article-to-comment |
| 98 | 98 | And I follow "Post a comment" |
| 99 | - Then "Post a comment" should not be visible within "#article" | |
| 99 | + Then "Post comment" should not be visible within "#article" | ... | ... |
features/manage_categories.feature
| ... | ... | @@ -27,5 +27,7 @@ Feature: manage categories |
| 27 | 27 | Then I should not see "Beans" |
| 28 | 28 | And I should not see "Potatoes" |
| 29 | 29 | When I follow "Show" |
| 30 | + And I wait 0.5 seconds for Services show animation to finish | |
| 31 | + And I follow "Show" | |
| 30 | 32 | Then I should see "Beans" |
| 31 | 33 | And I should see "Potatoes" | ... | ... |
features/manage_users.feature
| ... | ... | @@ -15,7 +15,7 @@ Background: |
| 15 | 15 | Scenario: deactive user |
| 16 | 16 | Given I follow "Deactivate user" within "tr[title='Joao Silva']" |
| 17 | 17 | When I confirm the browser dialog |
| 18 | - Then the "tr[title='Joao Silva'] td.actions a.icon-activate-user" button should be enabled | |
| 18 | + Then the field "tr[title='Joao Silva'] td.actions a.icon-activate-user" should be enabled | |
| 19 | 19 | |
| 20 | 20 | @selenium |
| 21 | 21 | Scenario: activate user |
| ... | ... | @@ -23,7 +23,7 @@ Background: |
| 23 | 23 | And I confirm the browser dialog |
| 24 | 24 | And I follow "Activate user" within "tr[title='Paulo Santos']" |
| 25 | 25 | When I confirm the browser dialog |
| 26 | - Then the "tr[title='Paulo Santos'] td.actions a.icon-deactivate-user" button should be enabled | |
| 26 | + Then the field "tr[title='Paulo Santos'] td.actions a.icon-deactivate-user" should be enabled | |
| 27 | 27 | |
| 28 | 28 | @selenium |
| 29 | 29 | Scenario: remove user |
| ... | ... | @@ -36,7 +36,7 @@ Background: |
| 36 | 36 | Scenario: admin user |
| 37 | 37 | Given I follow "Set admin role" within "tr[title='Joao Silva']" |
| 38 | 38 | When I confirm the browser dialog |
| 39 | - Then the "tr[title='Joao Silva'] td.actions a.icon-reset-admin-role" button should be enabled | |
| 39 | + Then the field "tr[title='Joao Silva'] td.actions a.icon-reset-admin-role" should be enabled | |
| 40 | 40 | |
| 41 | 41 | @selenium |
| 42 | 42 | Scenario: unadmin user |
| ... | ... | @@ -44,4 +44,4 @@ Background: |
| 44 | 44 | And I confirm the browser dialog |
| 45 | 45 | And I follow "Reset admin role" within "tr[title='Paulo Santos']" |
| 46 | 46 | When I confirm the browser dialog |
| 47 | - Then the "tr[title='Paulo Santos'] td.actions a.icon-set-admin-role" button should be enabled | |
| 47 | + Then the field "tr[title='Paulo Santos'] td.actions a.icon-set-admin-role" should be enabled | ... | ... |
features/secret_community.feature
features/send_email_to_organization_members.feature
| ... | ... | @@ -31,7 +31,8 @@ Feature: send emails to organization members |
| 31 | 31 | Scenario: Send e-mail to members |
| 32 | 32 | Given I am logged in as "joaosilva" |
| 33 | 33 | And I go to Sample Community's members management |
| 34 | - And I follow "Send e-mail to members" | |
| 34 | + And I check "checkbox-manoel" | |
| 35 | + And I press "Send e-mail to members" | |
| 35 | 36 | And I fill in "Subject" with "Hello, member!" |
| 36 | 37 | And I fill in "Body" with "We have some news" |
| 37 | 38 | When I press "Send" |
| ... | ... | @@ -40,7 +41,8 @@ Feature: send emails to organization members |
| 40 | 41 | Scenario: Not send e-mail to members if subject is blank |
| 41 | 42 | Given I am logged in as "joaosilva" |
| 42 | 43 | And I go to Sample Community's members management |
| 43 | - And I follow "Send e-mail to members" | |
| 44 | + And I check "checkbox-manoel" | |
| 45 | + And I press "Send e-mail to members" | |
| 44 | 46 | And I fill in "Body" with "We have some news" |
| 45 | 47 | When I press "Send" |
| 46 | 48 | Then I should be on /profile/sample-community/send_mail |
| ... | ... | @@ -48,7 +50,8 @@ Feature: send emails to organization members |
| 48 | 50 | Scenario: Not send e-mail to members if body is blank |
| 49 | 51 | Given I am logged in as "joaosilva" |
| 50 | 52 | And I go to Sample Community's members management |
| 51 | - And I follow "Send e-mail to members" | |
| 53 | + And I check "checkbox-manoel" | |
| 54 | + And I press "Send e-mail to members" | |
| 52 | 55 | And I fill in "Subject" with "Hello, user!" |
| 53 | 56 | When I press "Send" |
| 54 | 57 | Then I should be on /profile/sample-community/send_mail |
| ... | ... | @@ -56,7 +59,8 @@ Feature: send emails to organization members |
| 56 | 59 | Scenario: Cancel creation of mailing |
| 57 | 60 | Given I am logged in as "joaosilva" |
| 58 | 61 | And I go to Sample Community's members management |
| 59 | - And I follow "Send e-mail to members" | |
| 62 | + And I check "checkbox-manoel" | |
| 63 | + And I press "Send e-mail to members" | |
| 60 | 64 | When I follow "Cancel e-mail" |
| 61 | 65 | Then I should be on Sample Community's members management |
| 62 | 66 | ... | ... |
features/step_definitions/custom_web_steps.rb
| 1 | 1 | Then /^"([^"]*)" should not be visible within "([^"]*)"$/ do |text, selector| |
| 2 | - if page.has_content?(text) | |
| 3 | - page.should have_no_css(selector, :text => text, :visible => false) | |
| 4 | - end | |
| 2 | + page.should have_no_css selector, text: text, visible: false | |
| 5 | 3 | end |
| 6 | 4 | |
| 7 | 5 | Then /^"([^"]*)" should be visible within "([^"]*)"$/ do |text, selector| |
| 8 | - if page.has_content?(text) | |
| 9 | - page.should have_css(selector, :text => text, :visible => false) | |
| 10 | - end | |
| 6 | + page.should have_css selector, text: text, visible: false | |
| 11 | 7 | end |
| 12 | 8 | |
| 13 | 9 | Then /^I should see "([^"]*)" link$/ do |text| |
| ... | ... | @@ -22,14 +18,14 @@ When /^I should see "([^\"]+)" linking to "([^\"]+)"$/ do |text, href| |
| 22 | 18 | page.should have_xpath("//a[@href='#{href}']") |
| 23 | 19 | end |
| 24 | 20 | |
| 25 | -Then /^the "([^"]*)" button should be disabled$/ do |selector| | |
| 26 | - field = find(selector) | |
| 27 | - field['disabled'].should be_truthy | |
| 28 | -end | |
| 21 | +Then /^the field "([^"]*)" should be (enabled|disabled)$/ do |selector, status| | |
| 22 | + field = page.find(:css, selector) | |
| 29 | 23 | |
| 30 | -Then /^the "([^"]*)" button should be enabled$/ do |selector| | |
| 31 | - field = find(selector) | |
| 32 | - field['disabled'].should_not be_truthy | |
| 24 | + if status == 'enabled' | |
| 25 | + field.disabled?.should_not be_truthy | |
| 26 | + else | |
| 27 | + field.disabled?.should be_truthy | |
| 28 | + end | |
| 33 | 29 | end |
| 34 | 30 | |
| 35 | 31 | When /^I reload and wait for the page$/ do | ... | ... |
features/step_definitions/web_steps.rb
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | |
| 8 | 8 | require 'uri' |
| 9 | 9 | require 'cgi' |
| 10 | -require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) | |
| 10 | +require_relative '../support/paths' | |
| 11 | 11 | |
| 12 | 12 | module WithinHelpers |
| 13 | 13 | def with_scope(locator) |
| ... | ... | @@ -39,37 +39,15 @@ end |
| 39 | 39 | |
| 40 | 40 | When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| |
| 41 | 41 | with_scope(selector) do |
| 42 | - begin | |
| 43 | - click_link(link, :match => :prefer_exact) | |
| 44 | - rescue Selenium::WebDriver::Error::UnknownError => selenium_error | |
| 45 | - if selenium_error.message.start_with? 'Element is not clickable at point' | |
| 46 | - link = find_link(link) | |
| 47 | - href = link[:href] | |
| 48 | - onclick = link[:onClick] | |
| 49 | - | |
| 50 | - warn "#{selenium_error.message}\n\n"\ | |
| 51 | - "Trying to overcome this by:\n" | |
| 52 | - | |
| 53 | - onclick_return = true | |
| 54 | - | |
| 55 | - unless onclick.nil? | |
| 56 | - warn "\t* Running onClick JS:\n"\ | |
| 57 | - "\t\t'#{onclick}'\n" | |
| 58 | - onclick_return = page.execute_script onclick | |
| 59 | - end | |
| 60 | - | |
| 61 | - if onclick_return | |
| 62 | - warn "\t* Redirecting you to the link's href:\n"\ | |
| 63 | - "\t\t'#{href}'\n" | |
| 64 | - | |
| 65 | - visit href | |
| 66 | - end | |
| 67 | - | |
| 68 | - warn "\nGood luck and be careful that this may produce hidden links to work on tests!\n" | |
| 69 | - else | |
| 70 | - raise selenium_error | |
| 71 | - end | |
| 42 | + link = find :link_or_button, link, match: :prefer_exact | |
| 43 | + # If the link has child elements, then $(link).click() has no effect, | |
| 44 | + # so find the first child and click on it. | |
| 45 | + if Capybara.default_driver == :selenium | |
| 46 | + target = link.all('*').first || link | |
| 47 | + else | |
| 48 | + target = link | |
| 72 | 49 | end |
| 50 | + target.click | |
| 73 | 51 | end |
| 74 | 52 | end |
| 75 | 53 | ... | ... |
features/support/debug.rb
features/support/env.rb
| ... | ... | @@ -65,5 +65,13 @@ Before do |
| 65 | 65 | fixtures_folder = Rails.root.join('test', 'fixtures') |
| 66 | 66 | fixtures = ['environments', 'roles'] |
| 67 | 67 | ActiveRecord::Fixtures.create_fixtures(fixtures_folder, fixtures) |
| 68 | + | |
| 69 | + # The same browser session is used across tests, so expire caching | |
| 70 | + # can create changes from scenario to another. | |
| 71 | + e=Environment.default | |
| 72 | + e.home_cache_in_minutes = 0 | |
| 73 | + e.general_cache_in_minutes = 0 | |
| 74 | + e.profile_cache_in_minutes = 0 | |
| 75 | + e.save | |
| 68 | 76 | end |
| 69 | 77 | ... | ... |
gitignore.example
lib/file_presenter.rb
lib/noosfero/api/v1/articles.rb
| ... | ... | @@ -165,6 +165,37 @@ module Noosfero |
| 165 | 165 | end |
| 166 | 166 | end |
| 167 | 167 | |
| 168 | + desc "Returns the total followers for the article" do | |
| 169 | + detail 'Get the followers of a specific article by id' | |
| 170 | + failure [[403, 'Forbidden']] | |
| 171 | + named 'ArticleFollowers' | |
| 172 | + end | |
| 173 | + get ':id/followers' do | |
| 174 | + article = find_article(environment.articles, params[:id]) | |
| 175 | + total = article.person_followers.count | |
| 176 | + {:total_followers => total} | |
| 177 | + end | |
| 178 | + | |
| 179 | + desc "Add a follower for the article" do | |
| 180 | + detail 'Add the current user identified by private token, like a follower of a article' | |
| 181 | + params Noosfero::API::Entities::UserLogin.documentation | |
| 182 | + failure [[401, 'Unauthorized']] | |
| 183 | + named 'ArticleFollow' | |
| 184 | + end | |
| 185 | + post ':id/follow' do | |
| 186 | + authenticate! | |
| 187 | + article = find_article(environment.articles, params[:id]) | |
| 188 | + if article.article_followers.exists?(:person_id => current_person.id) | |
| 189 | + {:success => false, :already_follow => true} | |
| 190 | + else | |
| 191 | + article_follower = ArticleFollower.new | |
| 192 | + article_follower.article = article | |
| 193 | + article_follower.person = current_person | |
| 194 | + article_follower.save! | |
| 195 | + {:success => true} | |
| 196 | + end | |
| 197 | + end | |
| 198 | + | |
| 168 | 199 | desc 'Return the children of a article identified by id' do |
| 169 | 200 | detail 'Get all children articles of a specific article' |
| 170 | 201 | params Noosfero::API::Entities::Article.documentation | ... | ... |
lib/noosfero/version.rb
lib/noosfero/vote_ext.rb
| ... | ... | @@ -2,10 +2,10 @@ require_dependency 'models/vote' |
| 2 | 2 | |
| 3 | 3 | class Vote |
| 4 | 4 | |
| 5 | - validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id], :if => :allow_duplicated_vote? | |
| 5 | + validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id], :unless => :allow_duplicate? | |
| 6 | 6 | |
| 7 | - def allow_duplicated_vote? | |
| 8 | - voter.present? | |
| 7 | + def allow_duplicate? | |
| 8 | + voter.blank? | |
| 9 | 9 | end |
| 10 | 10 | |
| 11 | 11 | validate :verify_target_archived | ... | ... |
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +namespace :cache do | |
| 2 | + task :private_files => :environment do | |
| 3 | + require 'sdbm' | |
| 4 | + | |
| 5 | + hash = {} | |
| 6 | + UploadedFile.where(:published => false).find_each do |uploaded_file| | |
| 7 | + hash[uploaded_file.public_filename] = uploaded_file.full_path | |
| 8 | + end | |
| 9 | + | |
| 10 | + dbm = SDBM.open(UploadedFile::DBM_PRIVATE_FILE) | |
| 11 | + dbm.update(hash) | |
| 12 | + dbm.close | |
| 13 | + end | |
| 14 | +end | ... | ... |
plugins/oauth_client/lib/ext/profile.rb
| 1 | 1 | require_dependency 'profile' |
| 2 | 2 | |
| 3 | -Profile.descendants.each do |subclass| | |
| 4 | - subclass.class_eval do | |
| 3 | +class Profile | |
| 5 | 4 | |
| 6 | - has_many :oauth_auths, foreign_key: :profile_id, class_name: 'OauthClientPlugin::Auth', dependent: :destroy | |
| 7 | - has_many :oauth_providers, through: :oauth_auths, source: :provider | |
| 5 | + has_many :oauth_auths, foreign_key: :profile_id, class_name: 'OauthClientPlugin::Auth', dependent: :destroy | |
| 6 | + has_many :oauth_providers, through: :oauth_auths, source: :provider | |
| 8 | 7 | |
| 9 | - end | |
| 10 | 8 | end | ... | ... |
plugins/organization_ratings/features/rate_community.feature
| ... | ... | @@ -33,4 +33,4 @@ Feature: rate_community |
| 33 | 33 | Given I am on mycommunity's homepage |
| 34 | 34 | When I follow "Rate this Community" |
| 35 | 35 | Then I should see "Joao Silva" within ".star-profile-name" |
| 36 | - And I should see Joao Silva's profile image | |
| 37 | 36 | \ No newline at end of file |
| 37 | + And I should see Joao Silva's profile image | ... | ... |
plugins/organization_ratings/features/vote_once_disable_cooldown.feature
0 → 100644
| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | +Feature: vote_once_disable_cooldown | |
| 2 | + As a admin | |
| 3 | + I want to disable the cooldown time when vote once is enabled | |
| 4 | + Making it clearly that there is no cooldown when vote once is enabled | |
| 5 | + | |
| 6 | + Background: | |
| 7 | + Given plugin "OrganizationRatings" is enabled on environment | |
| 8 | + And I am logged in as admin | |
| 9 | + And I go to /admin/plugins | |
| 10 | + And I check "Organization Ratings" | |
| 11 | + And I press "Save changes" | |
| 12 | + | |
| 13 | + @selenium | |
| 14 | + Scenario: disable or enable the cooldown field when vote on is checked or unchecked | |
| 15 | + Given I follow "Administration" | |
| 16 | + And I follow "Plugins" | |
| 17 | + And I follow "Configuration" | |
| 18 | + And the field "#organization_ratings_config_cooldown" should be enabled | |
| 19 | + And I check "Vote once" | |
| 20 | + And the field "#organization_ratings_config_cooldown" should be disabled | |
| 21 | + And I uncheck "Vote once" | |
| 22 | + Then the field "#organization_ratings_config_cooldown" should be enabled | |
| 23 | + | ... | ... |
plugins/organization_ratings/lib/organization_ratings_plugin.rb
plugins/organization_ratings/public/organization_rating_management.js
| ... | ... | @@ -9,8 +9,8 @@ |
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | cacheDom: function() { |
| 12 | - this.$vote_once_checkbox = $("#environment_organization_ratings_vote_once"); | |
| 13 | - this.$hours_timer_input = $("#environment_organization_ratings_cooldown"); | |
| 12 | + this.$vote_once_checkbox = $("#organization_ratings_config_vote_once"); | |
| 13 | + this.$hours_timer_input = $("#organization_ratings_config_cooldown"); | |
| 14 | 14 | }, |
| 15 | 15 | |
| 16 | 16 | |
| ... | ... | @@ -21,10 +21,22 @@ |
| 21 | 21 | |
| 22 | 22 | verifyHoursTimerDisable: function() { |
| 23 | 23 | if (this.$vote_once_checkbox.is(":checked")) { |
| 24 | - this.$hours_timer_input.attr("disabled", "disabled"); | |
| 24 | + //this.$hours_timer_input.attr("disabled", "disabled"); | |
| 25 | + this.disableVoteOnce(); | |
| 25 | 26 | } else { |
| 26 | - this.$hours_timer_input.removeAttr("disabled"); | |
| 27 | + //this.$hours_timer_input.removeAttr("disabled"); | |
| 28 | + this.enableVoteOnce(); | |
| 27 | 29 | } |
| 30 | + }, | |
| 31 | + | |
| 32 | + | |
| 33 | + enableVoteOnce: function() { | |
| 34 | + this.$hours_timer_input.removeAttr("disabled"); | |
| 35 | + }, | |
| 36 | + | |
| 37 | + | |
| 38 | + disableVoteOnce: function() { | |
| 39 | + this.$hours_timer_input.attr("disabled", "disabled"); | |
| 28 | 40 | } |
| 29 | 41 | } |
| 30 | 42 | ... | ... |
plugins/organization_ratings/public/style.css
| ... | ... | @@ -14,11 +14,11 @@ |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | .star-negative { |
| 17 | - background-image: url('public/images/star-negative.png'); | |
| 17 | + background-image: url('images/star-negative.png'); | |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | .star-positive { |
| 21 | - background-image: url('public/images/star-positive.png'); | |
| 21 | + background-image: url('images/star-positive.png'); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | .small-star-negative, .small-star-positive { |
| ... | ... | @@ -31,11 +31,11 @@ |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | .small-star-negative { |
| 34 | - background-image: url('public/images/small-star-negative.png'); | |
| 34 | + background-image: url('images/small-star-negative.png'); | |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | .small-star-positive { |
| 38 | - background-image: url('public/images/small-star-positive.png'); | |
| 38 | + background-image: url('images/small-star-positive.png'); | |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | .medium-star-negative, .medium-star-positive { |
| ... | ... | @@ -48,11 +48,11 @@ |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | .medium-star-positive { |
| 51 | - background-image: url('public/images/star-positive-medium.png'); | |
| 51 | + background-image: url('images/star-positive-medium.png'); | |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | .medium-star-negative { |
| 55 | - background-image: url('public/images/star-negative-medium.png'); | |
| 55 | + background-image: url('images/star-negative-medium.png'); | |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | .star-hide { | ... | ... |
plugins/people_block/lib/ext/person.rb
plugins/people_block/test/unit/members_block_test.rb
| ... | ... | @@ -280,6 +280,21 @@ class MembersBlockTest < ActionView::TestCase |
| 280 | 280 | assert_includes block.roles, Profile::Roles.moderator(owner.environment.id) |
| 281 | 281 | end |
| 282 | 282 | |
| 283 | + should 'count number of profiles by role' do | |
| 284 | + owner = fast_create(Community) | |
| 285 | + profile1 = fast_create(Person, {:public_profile => true}) | |
| 286 | + profile2 = fast_create(Person, {:public_profile => true}) | |
| 287 | + | |
| 288 | + owner.add_member profile2 | |
| 289 | + owner.add_moderator profile1 | |
| 290 | + | |
| 291 | + block = MembersBlock.new | |
| 292 | + block.visible_role = Profile::Roles.moderator(owner.environment.id).key | |
| 293 | + block.expects(:owner).returns(owner).at_least_once | |
| 294 | + | |
| 295 | + assert_equivalent [profile1], block.profile_list | |
| 296 | + end | |
| 297 | + | |
| 283 | 298 | protected |
| 284 | 299 | include NoosferoTestHelper |
| 285 | 300 | ... | ... |
plugins/pg_search/test/unit/pg_search_plugin_test.rb
| ... | ... | @@ -25,7 +25,8 @@ class PgSearchPluginTest < ActiveSupport::TestCase |
| 25 | 25 | profile1 = fast_create(Profile, :identifier => 'profile1', :name => 'debugger') |
| 26 | 26 | profile2 = fast_create(Profile, :identifier => 'profile2', :name => 'profile admin debugger') |
| 27 | 27 | profile3 = fast_create(Profile, :identifier => 'profile3', :name => 'admin debugger') |
| 28 | - assert_equal [profile2, profile3, profile1], search(Profile, 'profile admin deb') | |
| 28 | + profile4 = fast_create(Profile, :identifier => 'profile4', :name => 'simple user') | |
| 29 | + assert_equal [profile2, profile3, profile1, profile4], search(Profile, 'profile admin deb') | |
| 29 | 30 | end |
| 30 | 31 | |
| 31 | 32 | should 'locate profile escaping special characters' do | ... | ... |
plugins/site_tour/lib/ext/person.rb
plugins/stoa/test/functional/account_controller_test.rb
plugins/sub_organizations/views/sub_organizations_plugin_profile/_full_related_organizations.html.erb
| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | <%= profile_image_link organization, :big, 'div' %> |
| 11 | 11 | </div> |
| 12 | 12 | <div class="related-organizations-item-column-right"> |
| 13 | - <%= link_to_homepage(organization.name, organization.identifier, :class => "search-result-title") %> | |
| 13 | + <%= link_to_homepage(organization.name, organization, :class => "search-result-title") %> | |
| 14 | 14 | <div class="related-organizations-description"> |
| 15 | 15 | <% if organization.description %> |
| 16 | 16 | <% body_stripped = strip_tags(organization.description) %> | ... | ... |
plugins/video/lib/video_plugin.rb
| ... | ... | @@ -33,10 +33,14 @@ class VideoPlugin < Noosfero::Plugin |
| 33 | 33 | end |
| 34 | 34 | |
| 35 | 35 | def article_extra_toolbar_buttons(content) |
| 36 | - if content.kind_of?(VideoPlugin::VideoGallery) | |
| 37 | - url = url_for(:action => 'new', :type=>'VideoPlugin::Video', :controller=>'cms', :parent_id => content.id) | |
| 38 | - {:title => _('New Video'), :url => url, :icon => 'button with-text icon-new'} | |
| 39 | - end | |
| 36 | + return [] if !content.kind_of?(VideoPlugin::VideoGallery) | |
| 37 | + { | |
| 38 | + :id=>"new-video-btn", | |
| 39 | + :class=>"button with-text icon-new", | |
| 40 | + :url=> {:action => 'new', :type=>'VideoPlugin::Video', :controller=>'cms', :parent_id => content.id}, | |
| 41 | + :title=>_("New Video"), | |
| 42 | + :icon => :new | |
| 43 | + } | |
| 40 | 44 | end |
| 41 | 45 | |
| 42 | 46 | end | ... | ... |
plugins/video/views/content_viewer/video_plugin/_video_gallery.html.erb
public/designs/themes/noosfero/style.css
public/javascripts/comment_order.js
| ... | ... | @@ -10,10 +10,9 @@ function send_order(order, url) { |
| 10 | 10 | }); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | - | |
| 14 | 13 | jQuery(document).ready(function(){ |
| 15 | 14 | jQuery("#comment_order").change(function(){ |
| 16 | - var url = jQuery("#page_url").val(); | |
| 15 | + var url = window.location.href; | |
| 17 | 16 | send_order(this.value, url); |
| 18 | 17 | }); |
| 19 | -}); | |
| 20 | 18 | \ No newline at end of file |
| 19 | +}); | ... | ... |
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | +(function($) { | |
| 2 | + | |
| 3 | + //Autocomplete to list members | |
| 4 | + $('#filter-name-autocomplete').autocomplete({ | |
| 5 | + minLength:2, | |
| 6 | + source:function(request,response){ | |
| 7 | + $.ajax({ | |
| 8 | + url:document.location.pathname+'/search_members', | |
| 9 | + dataType:'json', | |
| 10 | + data:{ | |
| 11 | + filter_name:request.term | |
| 12 | + }, | |
| 13 | + success:response | |
| 14 | + }); | |
| 15 | + } | |
| 16 | + }); | |
| 17 | +})(jQuery); | |
| 18 | + | |
| 19 | + | |
| 20 | +function toggle(source) { | |
| 21 | + checkboxes = document.getElementsByName('members_filtered[]'); | |
| 22 | + for(var i=0, n=checkboxes.length;i<n;i++) { | |
| 23 | + checkboxes[i].checked = source.checked; | |
| 24 | + } | |
| 25 | +} | ... | ... |
public/stylesheets/profile-list.scss
| ... | ... | @@ -207,3 +207,23 @@ |
| 207 | 207 | height: auto; |
| 208 | 208 | font-size: 12px; |
| 209 | 209 | } |
| 210 | +.action-profile-members .profile_link{ | |
| 211 | + position: relative; | |
| 212 | +} | |
| 213 | +.action-profile-members .profile_link span.new-profile:last-child{ | |
| 214 | + position: absolute; | |
| 215 | + top: 3px; | |
| 216 | + right: 2px; | |
| 217 | + text-transform: uppercase; | |
| 218 | + color: #FFF; | |
| 219 | + font-size: 9px; | |
| 220 | + background: #66CC33; | |
| 221 | + padding: 2px; | |
| 222 | + display: block; | |
| 223 | + width: 35px; | |
| 224 | + font-weight: 700; | |
| 225 | +} | |
| 226 | +.action-profile-members .profile_link .fn{ | |
| 227 | + font-style: normal; | |
| 228 | + color: #000; | |
| 229 | +} | ... | ... |
script/apacheconf
| ... | ... | @@ -17,7 +17,6 @@ when 'virtualhosts' |
| 17 | 17 | puts " #{server_directive} #{domain.name}" |
| 18 | 18 | server_directive = 'ServerAlias' |
| 19 | 19 | end |
| 20 | - puts " Include /usr/share/noosfero/util/chat/apache/xmpp.conf" | |
| 21 | 20 | puts " Include /etc/noosfero/apache/virtualhost.conf" |
| 22 | 21 | puts "</VirtualHost>" |
| 23 | 22 | end | ... | ... |
script/development
| ... | ... | @@ -23,7 +23,7 @@ start() { |
| 23 | 23 | trap stop INT TERM EXIT |
| 24 | 24 | whenever --write-crontab --set 'environment=development' |
| 25 | 25 | mkdir -p log |
| 26 | - touch log/development.log | |
| 26 | + touch log/development.log log/development_api.log | |
| 27 | 27 | if [ -z "$RAILS_RELATIVE_URL_ROOT" ]; then |
| 28 | 28 | unicorn_rails --config-file lib/noosfero/unicorn.rb --daemonize $@ |
| 29 | 29 | else |
| ... | ... | @@ -32,7 +32,7 @@ start() { |
| 32 | 32 | --config-file lib/noosfero/unicorn.rb \ |
| 33 | 33 | --daemonize |
| 34 | 34 | fi |
| 35 | - tail -n 0 -f log/development.log || true | |
| 35 | + tail -n 0 -f log/development.log log/development_api.log || true | |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | 38 | start $@ | ... | ... |
script/quick-start
test/fixtures/roles.yml
test/functional/cms_controller_test.rb
| ... | ... | @@ -1647,6 +1647,50 @@ class CmsControllerTest < ActionController::TestCase |
| 1647 | 1647 | assert_tag :tag => 'input', :attributes => {:name => 'article[accept_comments]', :value => 1, :type => 'checkbox'} |
| 1648 | 1648 | end |
| 1649 | 1649 | |
| 1650 | + should 'logged in user NOT be able to create topic on forum when topic creation is set to Me' do | |
| 1651 | + u = create_user('linux') | |
| 1652 | + login_as :linux | |
| 1653 | + profile.articles << f = Forum.new(:name => 'Forum for test', | |
| 1654 | + :topic_creation => 'self', | |
| 1655 | + :body => 'Forum Body') | |
| 1656 | + | |
| 1657 | + post :new, :profile => profile.identifier, :type => 'TinyMceArticle', | |
| 1658 | + :article => {:name => 'New Topic by linux', :body => 'Article Body', | |
| 1659 | + :parent_id => f.id} | |
| 1660 | + | |
| 1661 | + assert_template :access_denied | |
| 1662 | + assert_not_equal 'New Topic by linux', Article.last.name | |
| 1663 | + end | |
| 1664 | + | |
| 1665 | + should 'logged in user NOT be able to create topic on forum when topic creation is set to Friends/Members' do | |
| 1666 | + u = create_user('linux') | |
| 1667 | + login_as :linux | |
| 1668 | + profile.articles << f = Forum.new(:name => 'Forum for test', | |
| 1669 | + :topic_creation => 'related', | |
| 1670 | + :body => 'Forum Body') | |
| 1671 | + | |
| 1672 | + post :new, :profile => profile.identifier, :type => 'TinyMceArticle', | |
| 1673 | + :article => {:name => 'New Topic by linux', :body => 'Article Body', | |
| 1674 | + :parent_id => f.id} | |
| 1675 | + | |
| 1676 | + assert_template :access_denied | |
| 1677 | + assert_not_equal 'New Topic by linux', Article.last.name | |
| 1678 | + end | |
| 1679 | + | |
| 1680 | + should 'logged in user be able to create topic on forum when topic creation is set to Logged in users' do | |
| 1681 | + u = create_user('linux') | |
| 1682 | + login_as :linux | |
| 1683 | + profile.articles << f = Forum.new(:name => 'Forum for test', | |
| 1684 | + :topic_creation => 'users', | |
| 1685 | + :body => 'Forum Body') | |
| 1686 | + | |
| 1687 | + post :new, :profile => profile.identifier, :type => 'TinyMceArticle', | |
| 1688 | + :article => {:name => 'New Topic by linux', :body => 'Article Body', | |
| 1689 | + :parent_id => f.id} | |
| 1690 | + | |
| 1691 | + assert_equal 'New Topic by linux', Article.last.name | |
| 1692 | + end | |
| 1693 | + | |
| 1650 | 1694 | should 'display accept comments option when editing forum post with a different label' do |
| 1651 | 1695 | profile.articles << f = Forum.new(:name => 'Forum for test') |
| 1652 | 1696 | profile.articles << a = TinyMceArticle.new(:name => 'Forum post for test', :parent => f) | ... | ... |
test/functional/comment_controller_test.rb
| ... | ... | @@ -387,10 +387,26 @@ class CommentControllerTest < ActionController::TestCase |
| 387 | 387 | Article.record_timestamps = true |
| 388 | 388 | |
| 389 | 389 | login_as @profile.identifier |
| 390 | - xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' }, :confirm => 'true' | |
| 390 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:title => 'crap!', :body => 'I think that this article is crap' }, :confirm => 'true' | |
| 391 | 391 | assert_not_equal yesterday, page.reload.updated_at |
| 392 | 392 | end |
| 393 | 393 | |
| 394 | + should 'follow article when commenting' do | |
| 395 | + page = create(Article, :profile => profile, :name => 'myarticle', :body => 'the body of the text') | |
| 396 | + login_as @profile.identifier | |
| 397 | + | |
| 398 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:title => 'crap!', :body => 'I think that this article is crap', :follow_article => true}, :confirm => 'true' | |
| 399 | + assert_includes page.person_followers, @profile | |
| 400 | + end | |
| 401 | + | |
| 402 | + should 'not follow article when commenting' do | |
| 403 | + page = create(Article, :profile => profile, :name => 'myarticle', :body => 'the body of the text') | |
| 404 | + login_as @profile.identifier | |
| 405 | + | |
| 406 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:title => 'crap!', :body => 'I think that this article is crap', :follow_article => false }, :confirm => 'true' | |
| 407 | + assert_not_includes page.person_followers, @profile | |
| 408 | + end | |
| 409 | + | |
| 394 | 410 | should 'be able to mark comments as spam' do |
| 395 | 411 | login_as profile.identifier |
| 396 | 412 | article = fast_create(Article, :profile_id => profile.id) | ... | ... |
test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -51,27 +51,26 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 51 | 51 | assert_response :missing |
| 52 | 52 | end |
| 53 | 53 | |
| 54 | - should 'produce a download-link when article is a uploaded file' do | |
| 54 | + should 'produce a download-link when view page is true' do | |
| 55 | 55 | profile = create_user('someone').person |
| 56 | 56 | html = UploadedFile.create! :uploaded_data => fixture_file_upload('/files/500.html', 'text/html'), :profile => profile |
| 57 | 57 | html.save! |
| 58 | 58 | |
| 59 | - get :view_page, :profile => 'someone', :page => [ '500.html' ] | |
| 59 | + get :view_page, :profile => 'someone', :page => [ '500.html' ], :view => true | |
| 60 | 60 | |
| 61 | 61 | assert_response :success |
| 62 | - assert_match /#{html.public_filename}/, @response.body | |
| 62 | + assert_select "a[href=#{html.full_path}]" | |
| 63 | 63 | end |
| 64 | 64 | |
| 65 | - should 'download file when article is image' do | |
| 65 | + should 'download file when view page is blank' do | |
| 66 | 66 | profile = create_user('someone').person |
| 67 | 67 | image = UploadedFile.create! :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile |
| 68 | 68 | image.save! |
| 69 | 69 | |
| 70 | 70 | get :view_page, :profile => 'someone', :page => [ 'rails.png' ] |
| 71 | 71 | |
| 72 | - assert_response :success | |
| 73 | - assert_not_nil assigns(:page).data | |
| 74 | - assert_match /image\/png/, @response.headers['Content-Type'] | |
| 72 | + assert_response :redirect | |
| 73 | + assert_redirected_to image.public_filename | |
| 75 | 74 | end |
| 76 | 75 | |
| 77 | 76 | should 'display image on a page when article is image and has a view param' do |
| ... | ... | @@ -342,6 +341,27 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 342 | 341 | assert_tag :content => /list my comment/ |
| 343 | 342 | end |
| 344 | 343 | |
| 344 | + should 'order comments according to comments ordering option' do | |
| 345 | + article = fast_create(Article, :profile_id => profile.id) | |
| 346 | + for n in 1..24 | |
| 347 | + article.comments.create!(:author => profile, :title => "some title #{n}", :body => "some body #{n}") | |
| 348 | + end | |
| 349 | + | |
| 350 | + get 'view_page', :profile => profile.identifier, :page => article.path.split('/') | |
| 351 | + | |
| 352 | + for i in 1..12 | |
| 353 | + assert_tag :tag => 'div', :attributes => { :class => 'comment-details' }, :descendant => { :tag => 'h4', :content => "some title #{i}" } | |
| 354 | + assert_no_tag :tag => 'div', :attributes => { :class => 'comment-details' }, :descendant => { :tag => 'h4', :content => "some title #{i + 12}" } | |
| 355 | + end | |
| 356 | + | |
| 357 | + xhr :get, :view_page, :profile => profile.identifier, :page => article.path.split('/'), :comment_page => 1, :comment_order => 'newest' | |
| 358 | + | |
| 359 | + for i in 1..12 | |
| 360 | + assert_no_tag :tag => 'div', :attributes => { :class => 'comment-details' }, :descendant => { :tag => 'h4', :content => "some title #{i}" } | |
| 361 | + assert_tag :tag => 'div', :attributes => { :class => 'comment-details' }, :descendant => { :tag => 'h4', :content => "some title #{i + 12}" } | |
| 362 | + end | |
| 363 | + end | |
| 364 | + | |
| 345 | 365 | should 'redirect to new article path under an old path' do |
| 346 | 366 | p = create_user('test_user').person |
| 347 | 367 | a = p.articles.create(:name => 'old-name') |
| ... | ... | @@ -1291,18 +1311,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1291 | 1311 | assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => 'This button is expired.', :class => 'button with-text icon-edit disabled' } } |
| 1292 | 1312 | end |
| 1293 | 1313 | |
| 1294 | - should 'remove email from article followers when unfollow' do | |
| 1295 | - profile = create_user('testuser').person | |
| 1296 | - follower_email = 'john@doe.br' | |
| 1297 | - article = profile.articles.create(:name => 'test') | |
| 1298 | - article.followers = [follower_email] | |
| 1299 | - article.save | |
| 1300 | - | |
| 1301 | - assert_includes Article.find(article.id).followers, follower_email | |
| 1302 | - post :view_page, :profile => profile.identifier, :page => [article.name], :unfollow => 'commit', :email => follower_email | |
| 1303 | - assert_not_includes Article.find(article.id).followers, follower_email | |
| 1304 | - end | |
| 1305 | - | |
| 1306 | 1314 | should 'not display comments marked as spam' do |
| 1307 | 1315 | article = fast_create(Article, :profile_id => profile.id) |
| 1308 | 1316 | ham = fast_create(Comment, :source_id => article.id, :source_type => 'Article', :title => 'some content') |
| ... | ... | @@ -1377,7 +1385,7 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1377 | 1385 | assert_equal 15, article.comments.count |
| 1378 | 1386 | |
| 1379 | 1387 | get 'view_page', :profile => profile.identifier, :page => article.path.split('/') |
| 1380 | - assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{article.path}?comment_page=2", :rel => 'next' } | |
| 1388 | + assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{article.path}?comment_order=oldest&comment_page=2", :rel => 'next' } | |
| 1381 | 1389 | end |
| 1382 | 1390 | |
| 1383 | 1391 | should 'not escape acceptable HTML in list of blog posts' do | ... | ... |
test/functional/profile_controller_test.rb
| ... | ... | @@ -18,6 +18,19 @@ class ProfileControllerTest < ActionController::TestCase |
| 18 | 18 | assert assigns(:friends) |
| 19 | 19 | end |
| 20 | 20 | |
| 21 | + should 'remove person from article followers when unfollow' do | |
| 22 | + profile = create_user('testuser').person | |
| 23 | + follower = create_user('follower').person | |
| 24 | + article = profile.articles.create(:name => 'test') | |
| 25 | + article.person_followers = [follower] | |
| 26 | + article.save | |
| 27 | + login_as('follower') | |
| 28 | + article.reload | |
| 29 | + assert_includes Article.find(article.id).person_followers, follower | |
| 30 | + post :unfollow_article, :article_id => article.id | |
| 31 | + assert_not_includes Article.find(article.id).person_followers, follower | |
| 32 | + end | |
| 33 | + | |
| 21 | 34 | should 'point to manage friends in user is seeing his own friends' do |
| 22 | 35 | login_as('testuser') |
| 23 | 36 | get :friends |
| ... | ... | @@ -1338,6 +1351,24 @@ class ProfileControllerTest < ActionController::TestCase |
| 1338 | 1351 | assert_equivalent [scrap,activity], assigns(:activities).map(&:activity) |
| 1339 | 1352 | end |
| 1340 | 1353 | |
| 1354 | + should "follow an article" do | |
| 1355 | + article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | |
| 1356 | + login_as(@profile.identifier) | |
| 1357 | + post :follow_article, :profile => profile.identifier, :article_id => article.id | |
| 1358 | + assert_includes article.person_followers, @profile | |
| 1359 | + end | |
| 1360 | + | |
| 1361 | + should "unfollow an article" do | |
| 1362 | + article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | |
| 1363 | + article.person_followers << @profile | |
| 1364 | + article.save! | |
| 1365 | + assert_includes article.person_followers, @profile | |
| 1366 | + | |
| 1367 | + login_as(@profile.identifier) | |
| 1368 | + post :unfollow_article, :profile => profile.identifier, :article_id => article.id | |
| 1369 | + assert_not_includes article.person_followers, @profile | |
| 1370 | + end | |
| 1371 | + | |
| 1341 | 1372 | should "be logged in to leave comment on an activity" do |
| 1342 | 1373 | article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') |
| 1343 | 1374 | activity = ActionTracker::Record.last |
| ... | ... | @@ -1434,11 +1465,41 @@ class ProfileControllerTest < ActionController::TestCase |
| 1434 | 1465 | create_user_with_permission('profile_moderator_user', 'send_mail_to_members', community) |
| 1435 | 1466 | login_as('profile_moderator_user') |
| 1436 | 1467 | @controller.stubs(:locale).returns('pt') |
| 1468 | + | |
| 1437 | 1469 | assert_difference 'Delayed::Job.count', 1 do |
| 1438 | 1470 | post :send_mail, :profile => community.identifier, :mailing => {:subject => 'Hello', :body => 'We have some news'} |
| 1439 | 1471 | end |
| 1440 | 1472 | end |
| 1441 | 1473 | |
| 1474 | + should 'send to members_filtered if available' do | |
| 1475 | + community = fast_create(Community) | |
| 1476 | + create_user_with_permission('profile_moderator_user', 'send_mail_to_members', community) | |
| 1477 | + person = create_user('Any').person | |
| 1478 | + community.add_member(person) | |
| 1479 | + community.save! | |
| 1480 | + login_as('profile_moderator_user') | |
| 1481 | + | |
| 1482 | + post :send_mail, :profile => community.identifier, :mailing => {:subject => 'Hello', :body => 'We have some news'} | |
| 1483 | + assert_equivalent community.members, OrganizationMailing.last.recipients | |
| 1484 | + | |
| 1485 | + @request.session[:members_filtered] = [person.id] | |
| 1486 | + post :send_mail, :profile => community.identifier, :mailing => {:subject => 'RUN!!', :body => 'Run to the hills!!'} | |
| 1487 | + assert_equal [person], OrganizationMailing.last.recipients | |
| 1488 | + end | |
| 1489 | + | |
| 1490 | + should 'send email to all members if there is no valid member in members_filtered' do | |
| 1491 | + community = fast_create(Community) | |
| 1492 | + create_user_with_permission('profile_moderator_user', 'send_mail_to_members', community) | |
| 1493 | + person = create_user('Any').person | |
| 1494 | + community.add_member(person) | |
| 1495 | + community.save! | |
| 1496 | + login_as('profile_moderator_user') | |
| 1497 | + | |
| 1498 | + @request.session[:members_filtered] = [Profile.last.id+1] | |
| 1499 | + post :send_mail, :profile => community.identifier, :mailing => {:subject => 'RUN!!', :body => 'Run to the hills!!'} | |
| 1500 | + assert_empty OrganizationMailing.last.recipients | |
| 1501 | + end | |
| 1502 | + | |
| 1442 | 1503 | should 'save mailing' do |
| 1443 | 1504 | community = fast_create(Community) |
| 1444 | 1505 | create_user_with_permission('profile_moderator_user', 'send_mail_to_members', community) | ... | ... |
test/functional/profile_design_controller_test.rb
| ... | ... | @@ -311,6 +311,12 @@ class ProfileDesignControllerTest < ActionController::TestCase |
| 311 | 311 | assert_equal 999, @b1.article_id |
| 312 | 312 | end |
| 313 | 313 | |
| 314 | + should 'not be able to save a non editable block' do | |
| 315 | + Block.any_instance.expects(:editable?).returns(false) | |
| 316 | + post :save, :profile => 'designtestuser', :id => @b1.id, :block => { } | |
| 317 | + assert_response :forbidden | |
| 318 | + end | |
| 319 | + | |
| 314 | 320 | should 'be able to edit ProductsBlock' do |
| 315 | 321 | block = ProductsBlock.new |
| 316 | 322 | ... | ... |
test/functional/profile_members_controller_test.rb
| ... | ... | @@ -31,6 +31,31 @@ class ProfileMembersControllerTest < ActionController::TestCase |
| 31 | 31 | assert_template 'index' |
| 32 | 32 | end |
| 33 | 33 | |
| 34 | + should 'access index and filter members by name and roles' do | |
| 35 | + | |
| 36 | + ent = fast_create(Enterprise, :identifier => 'test_enterprise', :name => 'test enterprise') | |
| 37 | + roles = { | |
| 38 | + :admin => Profile::Roles.admin(Environment.default), | |
| 39 | + :member => Profile::Roles.member(Environment.default) | |
| 40 | + } | |
| 41 | + | |
| 42 | + member = create_user('test_member', :email => 'testmember@test.com.br').person | |
| 43 | + member.add_role(roles[:member], ent) | |
| 44 | + | |
| 45 | + admin = create_user('test_admin').person | |
| 46 | + admin.add_role roles[:admin], ent | |
| 47 | + | |
| 48 | + user = create_user_with_permission('test_user', 'manage_memberships', ent) | |
| 49 | + login_as :test_user | |
| 50 | + | |
| 51 | + post :index, :profile => 'test_enterprise' , :filters => {:name => 'testmember@test.com.br', :roles => [roles[:member].id]} | |
| 52 | + | |
| 53 | + assert_response :success | |
| 54 | + assert_template 'index' | |
| 55 | + | |
| 56 | + assert_includes assigns(:data)[:members], member | |
| 57 | + end | |
| 58 | + | |
| 34 | 59 | should 'show form to change role' do |
| 35 | 60 | ent = fast_create(Enterprise, :identifier => 'test_enterprise', :name => 'test enterprise') |
| 36 | 61 | role = Profile::Roles.member(Environment.default) |
| ... | ... | @@ -171,7 +196,7 @@ class ProfileMembersControllerTest < ActionController::TestCase |
| 171 | 196 | login_as :test_user |
| 172 | 197 | |
| 173 | 198 | get :index, :profile => community.identifier |
| 174 | - assert_tag :tag => 'a', :attributes => {:href => /send_mail/} | |
| 199 | + assert_tag :tag => 'input', :attributes => {:value => 'Send e-mail to members'} | |
| 175 | 200 | end |
| 176 | 201 | |
| 177 | 202 | should 'not display send email to members if doesn\'t have the permission' do | ... | ... |
test/integration/enable_disable_features_test.rb
| ... | ... | @@ -13,17 +13,15 @@ class EnableDisableFeaturesTest < ActionDispatch::IntegrationTest |
| 13 | 13 | assert_tag :tag => 'input', :attributes => { :name => 'environment[enabled_features][]', :value => 'feature2' } |
| 14 | 14 | assert_tag :tag => 'input', :attributes => { :name => 'environment[enabled_features][]', :value => 'feature3' } |
| 15 | 15 | |
| 16 | - post '/admin/features/update' | |
| 17 | - assert_response :redirect | |
| 16 | + post_via_redirect '/admin/features/update' | |
| 17 | + assert_response :success | |
| 18 | 18 | |
| 19 | - follow_redirect! | |
| 20 | 19 | assert_response :success |
| 21 | 20 | assert_equal '/admin/features', path |
| 22 | 21 | |
| 23 | - post '/admin/features/update', :environments => { :enabled_features => [ 'feature1' ], :organization_approval_method => 'region' } | |
| 24 | - assert_response :redirect | |
| 22 | + post_via_redirect '/admin/features/update', :environments => { :enabled_features => [ 'feature1' ], :organization_approval_method => 'region' } | |
| 23 | + assert_response :success | |
| 25 | 24 | |
| 26 | - follow_redirect! | |
| 27 | 25 | assert_equal '/admin/features', path |
| 28 | 26 | |
| 29 | 27 | end | ... | ... |
test/integration/enterprise_registration_test.rb
| ... | ... | @@ -61,10 +61,9 @@ class EnterpriseRegistrationTest < ActionDispatch::IntegrationTest |
| 61 | 61 | assert_response :success |
| 62 | 62 | assert_tag :form, :attributes => { :action => "/myprofile/myorg/enterprise_validation/approve/#{code}" } |
| 63 | 63 | |
| 64 | - post "/myprofile/myorg/enterprise_validation/approve/#{code}" | |
| 65 | - assert_response :redirect | |
| 64 | + post_via_redirect "/myprofile/myorg/enterprise_validation/approve/#{code}" | |
| 65 | + assert_response :success | |
| 66 | 66 | |
| 67 | - follow_redirect! | |
| 68 | 67 | assert_equal "/myprofile/myorg/enterprise_validation/view_processed/#{code}", path |
| 69 | 68 | assert_tag :span, :attributes => { :class => 'validation_approved' } |
| 70 | 69 | end | ... | ... |
test/integration/manage_documents_test.rb
| ... | ... | @@ -24,11 +24,10 @@ class ManageDocumentsTest < ActionDispatch::IntegrationTest |
| 24 | 24 | assert_tag :tag => 'form', :attributes => { :action => '/myprofile/myuser/cms/new', :method => /post/i } |
| 25 | 25 | |
| 26 | 26 | assert_difference 'Article.count' do |
| 27 | - post '/myprofile/myuser/cms/new', :type => 'TinyMceArticle', :article => { :name => 'my article', :body => 'this is the body of ther article'} | |
| 27 | + post_via_redirect '/myprofile/myuser/cms/new', :type => 'TinyMceArticle', :article => { :name => 'my article', :body => 'this is the body of ther article'} | |
| 28 | 28 | end |
| 29 | 29 | |
| 30 | - assert_response :redirect | |
| 31 | - follow_redirect! | |
| 30 | + assert_response :success | |
| 32 | 31 | a = Article.find_by_path('my-article') |
| 33 | 32 | assert_equal "/myuser/#{a.slug}", path |
| 34 | 33 | end |
| ... | ... | @@ -55,14 +54,13 @@ class ManageDocumentsTest < ActionDispatch::IntegrationTest |
| 55 | 54 | assert_tag :tag => 'form', :attributes => { :action => "/myprofile/myuser/cms/edit/#{article.id}", :method => /post/i } |
| 56 | 55 | |
| 57 | 56 | assert_no_difference 'Article.count' do |
| 58 | - post "/myprofile/myuser/cms/edit/#{article.id}", :article => { :name => 'my article', :body => 'this is the body of the article'} | |
| 57 | + post_via_redirect "/myprofile/myuser/cms/edit/#{article.id}", :article => { :name => 'my article', :body => 'this is the body of the article'} | |
| 59 | 58 | end |
| 60 | 59 | |
| 61 | 60 | article.reload |
| 62 | 61 | assert_equal 'this is the body of the article', article.body |
| 63 | 62 | |
| 64 | - assert_response :redirect | |
| 65 | - follow_redirect! | |
| 63 | + assert_response :success | |
| 66 | 64 | a = Article.find_by_path('my-article') |
| 67 | 65 | assert_equal "/myuser/#{a.slug}", path |
| 68 | 66 | end |
| ... | ... | @@ -84,10 +82,9 @@ class ManageDocumentsTest < ActionDispatch::IntegrationTest |
| 84 | 82 | assert_response :success |
| 85 | 83 | |
| 86 | 84 | assert_tag tag: 'a', attributes: { href: "/myprofile/myuser/cms/destroy/#{article.id}", 'data-confirm' => /Are you sure/ } |
| 87 | - post "/myprofile/myuser/cms/destroy/#{article.id}" | |
| 85 | + post_via_redirect "/myprofile/myuser/cms/destroy/#{article.id}" | |
| 88 | 86 | |
| 89 | - assert_response :redirect | |
| 90 | - follow_redirect! | |
| 87 | + assert_response :success | |
| 91 | 88 | assert_equal "/myuser", path |
| 92 | 89 | |
| 93 | 90 | # the article was actually deleted | ... | ... |
test/integration/manage_friendships_test.rb
| ... | ... | @@ -24,11 +24,10 @@ class ManageFriendshipsTest < ActionDispatch::IntegrationTest |
| 24 | 24 | get "/myprofile/#{@person.identifier}/friends/remove/#{@friend.id}" |
| 25 | 25 | assert_response :success |
| 26 | 26 | |
| 27 | - post "/myprofile/#{@person.identifier}/friends/remove/#{@friend.id}", | |
| 27 | + post_via_redirect "/myprofile/#{@person.identifier}/friends/remove/#{@friend.id}", | |
| 28 | 28 | :confirmation => '1' |
| 29 | - assert_response :redirect | |
| 29 | + assert_response :success | |
| 30 | 30 | |
| 31 | - follow_redirect! | |
| 32 | 31 | |
| 33 | 32 | assert assigns(:friends).empty? |
| 34 | 33 | refute @person.is_a_friend?(@friend) | ... | ... |
test/support/integration_test.rb
| ... | ... | @@ -14,9 +14,8 @@ class ActionDispatch::IntegrationTest |
| 14 | 14 | def login(username, password) |
| 15 | 15 | ActionDispatch::Integration::Session.any_instance.stubs(:https?).returns(true) |
| 16 | 16 | |
| 17 | - post '/account/login', :user => { :login => username, :password => password } | |
| 18 | - assert_response :redirect | |
| 19 | - follow_redirect! | |
| 17 | + post_via_redirect '/account/login', :user => { :login => username, :password => password } | |
| 18 | + assert_response :success | |
| 20 | 19 | assert_not_equal '/account/login', path |
| 21 | 20 | end |
| 22 | 21 | ... | ... |
| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | + | |
| 2 | +require_relative "../test_helper" | |
| 3 | + | |
| 4 | +class AccessControlTest < ActiveSupport::TestCase | |
| 5 | + | |
| 6 | + include ActsAsAccessor | |
| 7 | + | |
| 8 | + should 'raise exception if parameter is not a profile' do | |
| 9 | + assert_raises(TypeError) { member_relation_of(nil) } | |
| 10 | + end | |
| 11 | + | |
| 12 | + should 'Verify relation among member and community' do | |
| 13 | + person = fast_create(Person) | |
| 14 | + community = fast_create(Community) | |
| 15 | + assert_difference 'person.member_relation_of(community).count', 2 do | |
| 16 | + community.add_member(person) | |
| 17 | + end | |
| 18 | + end | |
| 19 | + | |
| 20 | + should 'Member does not belong to community' do | |
| 21 | + person = fast_create(Person) | |
| 22 | + community = fast_create(Community) | |
| 23 | + assert_nil person.member_since_date(community) | |
| 24 | + end | |
| 25 | + | |
| 26 | + should 'Verify if enter date of member in community is available' do | |
| 27 | + person = fast_create(Person) | |
| 28 | + community = fast_create(Community) | |
| 29 | + community.add_member(person) | |
| 30 | + | |
| 31 | + assert_instance_of Date, person.member_since_date(community) | |
| 32 | + end | |
| 33 | + | |
| 34 | +end | ... | ... |
test/unit/action_tracker_notification_test.rb
| ... | ... | @@ -89,7 +89,8 @@ class ActionTrackerNotificationTest < ActiveSupport::TestCase |
| 89 | 89 | end |
| 90 | 90 | |
| 91 | 91 | should "have comments through article action_tracker" do |
| 92 | - person = create_user.person | |
| 92 | + user = User.current = create_user | |
| 93 | + person = user.person | |
| 93 | 94 | article = create(TextileArticle, :profile_id => person.id) |
| 94 | 95 | process_delayed_job_queue |
| 95 | 96 | notification = ActionTrackerNotification.last | ... | ... |
test/unit/api/articles_test.rb
| ... | ... | @@ -39,6 +39,41 @@ class ArticlesTest < ActiveSupport::TestCase |
| 39 | 39 | assert_equal 403, last_response.status |
| 40 | 40 | end |
| 41 | 41 | |
| 42 | + should 'follow a article identified by id' do | |
| 43 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | |
| 44 | + post "/api/v1/articles/#{article.id}/follow?#{params.to_query}" | |
| 45 | + json = JSON.parse(last_response.body) | |
| 46 | + | |
| 47 | + assert_not_equal 401, last_response.status | |
| 48 | + assert_equal true, json['success'] | |
| 49 | + end | |
| 50 | + | |
| 51 | + should 'return the followers count of an article' do | |
| 52 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | |
| 53 | + article.person_followers << @person | |
| 54 | + | |
| 55 | + get "/api/v1/articles/#{article.id}?#{params.to_query}" | |
| 56 | + json = JSON.parse(last_response.body) | |
| 57 | + | |
| 58 | + assert_equal 200, last_response.status | |
| 59 | + assert_equal 1, json['article']['followers_count'] | |
| 60 | + end | |
| 61 | + | |
| 62 | + should 'return the followers of a article identified by id' do | |
| 63 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | |
| 64 | + | |
| 65 | + article_follower = ArticleFollower.new | |
| 66 | + article_follower.article = article | |
| 67 | + article_follower.person = @person | |
| 68 | + article_follower.save! | |
| 69 | + | |
| 70 | + get "/api/v1/articles/#{article.id}/followers?#{params.to_query}" | |
| 71 | + json = JSON.parse(last_response.body) | |
| 72 | + | |
| 73 | + assert_equal 200, last_response.status | |
| 74 | + assert_equal 1, json['total_followers'] | |
| 75 | + end | |
| 76 | + | |
| 42 | 77 | should 'list article children' do |
| 43 | 78 | article = create(Article, :profile_id => user.person.id, :name => "Parent") |
| 44 | 79 | child1 = create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some Child") | ... | ... |
test/unit/application_helper_test.rb
| ... | ... | @@ -1043,6 +1043,31 @@ class ApplicationHelperTest < ActionView::TestCase |
| 1043 | 1043 | assert_equal c.top_url, top_url |
| 1044 | 1044 | end |
| 1045 | 1045 | |
| 1046 | + should "Extra info with hash" do | |
| 1047 | + @plugins = mock | |
| 1048 | + @plugins.stubs(:dispatch_first).returns(false) | |
| 1049 | + env = Environment.default | |
| 1050 | + stubs(:environment).returns(env) | |
| 1051 | + stubs(:profile).returns(profile) | |
| 1052 | + profile = fast_create(Person, :environment_id => env.id) | |
| 1053 | + info = {:value =>_('New'), :class => 'new-profile'} | |
| 1054 | + html = profile_image_link(profile, size=:portrait, tag='li', extra_info = info) | |
| 1055 | + assert_tag_in_string html, :tag => 'span', :attributes => { :class => 'profile-image new-profile' } | |
| 1056 | + assert_tag_in_string html, :tag => 'span', :attributes => { :class => 'extra_info new-profile' }, :content => 'New' | |
| 1057 | + end | |
| 1058 | + | |
| 1059 | + should "Extra info without hash" do | |
| 1060 | + @plugins = mock | |
| 1061 | + @plugins.stubs(:dispatch_first).returns(false) | |
| 1062 | + env = Environment.default | |
| 1063 | + stubs(:environment).returns(env) | |
| 1064 | + stubs(:profile).returns(profile) | |
| 1065 | + profile = fast_create(Person, :environment_id => env.id) | |
| 1066 | + info = 'new' | |
| 1067 | + html = profile_image_link(profile, size=:portrait, tag='li', extra_info = info) | |
| 1068 | + assert_tag_in_string html, :tag => 'span', :attributes => { :class => 'extra_info' }, :content => 'new' | |
| 1069 | + end | |
| 1070 | + | |
| 1046 | 1071 | protected |
| 1047 | 1072 | include NoosferoTestHelper |
| 1048 | 1073 | ... | ... |
test/unit/article_block_test.rb
| ... | ... | @@ -140,6 +140,8 @@ class ArticleBlockTest < ActiveSupport::TestCase |
| 140 | 140 | block.article = file |
| 141 | 141 | block.save! |
| 142 | 142 | |
| 143 | + UploadedFile.any_instance.stubs(:url).returns('myhost.mydomain/path/to/file') | |
| 144 | + | |
| 143 | 145 | assert_tag_in_string instance_eval(&block.content), :tag => 'a', :content => _('Download') |
| 144 | 146 | end |
| 145 | 147 | ... | ... |
test/unit/article_test.rb
| ... | ... | @@ -7,7 +7,8 @@ class ArticleTest < ActiveSupport::TestCase |
| 7 | 7 | |
| 8 | 8 | def setup |
| 9 | 9 | ActiveSupport::TestCase::setup |
| 10 | - @profile = create_user('testing').person | |
| 10 | + user = User.current = create_user 'testing' | |
| 11 | + @profile = user.person | |
| 11 | 12 | end |
| 12 | 13 | attr_reader :profile |
| 13 | 14 | |
| ... | ... | @@ -21,6 +22,21 @@ class ArticleTest < ActiveSupport::TestCase |
| 21 | 22 | refute a.errors[:profile_id.to_s].present? |
| 22 | 23 | end |
| 23 | 24 | |
| 25 | + should 'keep unique users in list of followers' do | |
| 26 | + person1 = create_user('article_owner').person | |
| 27 | + person2 = create_user('article_follower').person | |
| 28 | + | |
| 29 | + article = fast_create(Article, :profile_id => person1.id) | |
| 30 | + | |
| 31 | + article.person_followers=[person2] | |
| 32 | + article.save | |
| 33 | + article.reload | |
| 34 | + article.person_followers=[person2] | |
| 35 | + article.save | |
| 36 | + | |
| 37 | + assert_equal 1, article.reload.person_followers.size | |
| 38 | + end | |
| 39 | + | |
| 24 | 40 | should 'require value for name' do |
| 25 | 41 | a = Article.new |
| 26 | 42 | a.valid? |
| ... | ... | @@ -468,14 +484,12 @@ class ArticleTest < ActiveSupport::TestCase |
| 468 | 484 | end |
| 469 | 485 | |
| 470 | 486 | should 'say that logged off user cannot see private article' do |
| 471 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 472 | 487 | article = fast_create(Article, :name => 'test article', :profile_id => profile.id, :published => false) |
| 473 | 488 | |
| 474 | 489 | refute article.display_to?(nil) |
| 475 | 490 | end |
| 476 | 491 | |
| 477 | 492 | should 'say that not member of profile cannot see private article' do |
| 478 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 479 | 493 | article = fast_create(Article, :name => 'test article', :profile_id => profile.id, :published => false) |
| 480 | 494 | person = create_user('test_user').person |
| 481 | 495 | |
| ... | ... | @@ -483,7 +497,6 @@ class ArticleTest < ActiveSupport::TestCase |
| 483 | 497 | end |
| 484 | 498 | |
| 485 | 499 | should 'say that member user can not see private article' do |
| 486 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 487 | 500 | article = fast_create(Article, :name => 'test article', :profile_id => profile.id, :published => false, :show_to_followers => false) |
| 488 | 501 | person = create_user('test_user').person |
| 489 | 502 | profile.affiliate(person, Profile::Roles.member(profile.environment.id)) |
| ... | ... | @@ -492,25 +505,23 @@ class ArticleTest < ActiveSupport::TestCase |
| 492 | 505 | end |
| 493 | 506 | |
| 494 | 507 | should 'say that profile admin can see private article' do |
| 495 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 508 | + org = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 496 | 509 | article = fast_create(Article, :name => 'test article', :profile_id => profile.id, :published => false) |
| 497 | - person = create_user('test_user').person | |
| 498 | - profile.affiliate(person, Profile::Roles.admin(profile.environment.id)) | |
| 510 | + org.affiliate(profile, Profile::Roles.admin(org.environment.id)) | |
| 499 | 511 | |
| 500 | - assert article.display_to?(person) | |
| 512 | + assert article.display_to?(profile) | |
| 501 | 513 | end |
| 502 | 514 | |
| 503 | 515 | should 'say that profile moderator can see private article' do |
| 504 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 505 | - article = fast_create(Article, :name => 'test article', :profile_id => profile.id, :published => false) | |
| 506 | - person = create_user('test_user').person | |
| 507 | - profile.affiliate(person, Profile::Roles.moderator(profile.environment.id)) | |
| 516 | + org = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 517 | + article = fast_create(Article, :name => 'test article', :profile_id => org.id, :published => false) | |
| 518 | + org.affiliate(profile, Profile::Roles.moderator(org.environment.id)) | |
| 508 | 519 | |
| 509 | - assert article.display_to?(person) | |
| 520 | + assert article.display_to?(profile) | |
| 510 | 521 | end |
| 511 | 522 | |
| 512 | 523 | should 'show article to non member if article public but profile private' do |
| 513 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile', :public_profile => false) | |
| 524 | + profile.update public_profile: false | |
| 514 | 525 | article = fast_create(Article, :name => 'test article', :profile_id => profile.id, :published => true) |
| 515 | 526 | person1 = create_user('test_user1').person |
| 516 | 527 | profile.affiliate(person1, Profile::Roles.member(profile.environment.id)) |
| ... | ... | @@ -522,7 +533,6 @@ class ArticleTest < ActiveSupport::TestCase |
| 522 | 533 | end |
| 523 | 534 | |
| 524 | 535 | should 'make new article private if created inside a private folder' do |
| 525 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 526 | 536 | folder = fast_create(Folder, :name => 'my_intranet', :profile_id => profile.id, :published => false) |
| 527 | 537 | article = fast_create(Article, :name => 'my private article', :profile_id => profile.id, :parent_id => folder.id) |
| 528 | 538 | |
| ... | ... | @@ -530,7 +540,6 @@ class ArticleTest < ActiveSupport::TestCase |
| 530 | 540 | end |
| 531 | 541 | |
| 532 | 542 | should 'save as private' do |
| 533 | - profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') | |
| 534 | 543 | folder = fast_create(Folder, :name => 'my_intranet', :profile_id => profile.id, :published => false) |
| 535 | 544 | article = fast_create(Article, :name => 'my private article') |
| 536 | 545 | article.profile = profile |
| ... | ... | @@ -1012,13 +1021,13 @@ class ArticleTest < ActiveSupport::TestCase |
| 1012 | 1021 | |
| 1013 | 1022 | should 'not notify activity by default on create' do |
| 1014 | 1023 | ActionTracker::Record.delete_all |
| 1015 | - create Article, :name => 'test', :profile_id => fast_create(Profile).id, :published => true | |
| 1024 | + create Article, :name => 'test', :profile_id => profile.id, :published => true | |
| 1016 | 1025 | assert_equal 0, ActionTracker::Record.count |
| 1017 | 1026 | end |
| 1018 | 1027 | |
| 1019 | 1028 | should 'not notify activity by default on update' do |
| 1020 | 1029 | ActionTracker::Record.delete_all |
| 1021 | - a = create Article, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true | |
| 1030 | + a = create Article, :name => 'bar', :profile_id => profile.id, :published => true | |
| 1022 | 1031 | a.name = 'foo' |
| 1023 | 1032 | a.save! |
| 1024 | 1033 | assert_equal 0, ActionTracker::Record.count |
| ... | ... | @@ -1026,13 +1035,13 @@ class ArticleTest < ActiveSupport::TestCase |
| 1026 | 1035 | |
| 1027 | 1036 | should 'not notify activity by default on destroy' do |
| 1028 | 1037 | ActionTracker::Record.delete_all |
| 1029 | - a = create Article, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true | |
| 1038 | + a = create Article, :name => 'bar', :profile_id => profile.id, :published => true | |
| 1030 | 1039 | a.destroy |
| 1031 | 1040 | assert_equal 0, ActionTracker::Record.count |
| 1032 | 1041 | end |
| 1033 | 1042 | |
| 1034 | 1043 | should 'create activity' do |
| 1035 | - a = create TextileArticle, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true | |
| 1044 | + a = create TextileArticle, :name => 'bar', :profile_id => profile.id, :published => true | |
| 1036 | 1045 | a.activity.destroy |
| 1037 | 1046 | assert_nil a.activity |
| 1038 | 1047 | |
| ... | ... | @@ -1212,10 +1221,9 @@ class ArticleTest < ActiveSupport::TestCase |
| 1212 | 1221 | end |
| 1213 | 1222 | |
| 1214 | 1223 | should 'get article galleries' do |
| 1215 | - p = fast_create(Profile) | |
| 1216 | - a = fast_create(Article, :profile_id => p.id) | |
| 1217 | - g = fast_create(Gallery, :profile_id => p.id) | |
| 1218 | - assert_equal [g], p.articles.galleries | |
| 1224 | + a = fast_create(Article, :profile_id => profile.id) | |
| 1225 | + g = fast_create(Gallery, :profile_id => profile.id) | |
| 1226 | + assert_equal [g], profile.articles.galleries | |
| 1219 | 1227 | end |
| 1220 | 1228 | |
| 1221 | 1229 | should 'has many translations' do |
| ... | ... | @@ -1236,7 +1244,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1236 | 1244 | end |
| 1237 | 1245 | |
| 1238 | 1246 | should 'validate inclusion of language' do |
| 1239 | - a = build(Article, :profile_id => fast_create(Profile).id) | |
| 1247 | + a = build(Article, :profile_id => profile.id) | |
| 1240 | 1248 | a.language = '12' |
| 1241 | 1249 | a.valid? |
| 1242 | 1250 | assert a.errors[:language.to_s].present? |
| ... | ... | @@ -1268,7 +1276,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1268 | 1276 | end |
| 1269 | 1277 | |
| 1270 | 1278 | should 'list possible translations' do |
| 1271 | - native_article = fast_create(Article, :language => 'pt', :profile_id => fast_create(Profile).id ) | |
| 1279 | + native_article = fast_create(Article, :language => 'pt', :profile_id => profile.id ) | |
| 1272 | 1280 | article_translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id) |
| 1273 | 1281 | possible_translations = native_article.possible_translations |
| 1274 | 1282 | refute possible_translations.include?('en') |
| ... | ... | @@ -1278,7 +1286,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1278 | 1286 | should 'verify if translation is already in use' do |
| 1279 | 1287 | native_article = fast_create(Article, :language => 'pt') |
| 1280 | 1288 | article_translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id) |
| 1281 | - a = build(Article, :profile => fast_create(Profile)) | |
| 1289 | + a = build(Article, :profile => profile) | |
| 1282 | 1290 | a.language = 'en' |
| 1283 | 1291 | a.translation_of = native_article |
| 1284 | 1292 | a.valid? |
| ... | ... | @@ -1290,7 +1298,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1290 | 1298 | |
| 1291 | 1299 | should 'verify if native translation is already in use' do |
| 1292 | 1300 | native_article = fast_create(Article, :language => 'pt') |
| 1293 | - a = build(Article, :profile => fast_create(Profile)) | |
| 1301 | + a = build(Article, :profile => profile) | |
| 1294 | 1302 | a.language = 'pt' |
| 1295 | 1303 | a.translation_of = native_article |
| 1296 | 1304 | a.valid? |
| ... | ... | @@ -1302,7 +1310,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1302 | 1310 | |
| 1303 | 1311 | should 'translation have a language' do |
| 1304 | 1312 | native_article = fast_create(Article, :language => 'pt') |
| 1305 | - a = build(Article, :profile_id => fast_create(Profile).id) | |
| 1313 | + a = build(Article, :profile_id => profile.id) | |
| 1306 | 1314 | a.translation_of = native_article |
| 1307 | 1315 | a.valid? |
| 1308 | 1316 | assert a.errors[:language.to_s].present? |
| ... | ... | @@ -1312,8 +1320,8 @@ class ArticleTest < ActiveSupport::TestCase |
| 1312 | 1320 | end |
| 1313 | 1321 | |
| 1314 | 1322 | should 'native translation have a language' do |
| 1315 | - native_article = fast_create(Article, :profile_id => fast_create(Profile).id ) | |
| 1316 | - a = build(Article, :profile_id => fast_create(Profile).id) | |
| 1323 | + native_article = fast_create(Article, :profile_id => profile.id ) | |
| 1324 | + a = build(Article, :profile_id => profile.id) | |
| 1317 | 1325 | a.language = 'en' |
| 1318 | 1326 | a.translation_of = native_article |
| 1319 | 1327 | a.valid? |
| ... | ... | @@ -1378,22 +1386,22 @@ class ArticleTest < ActiveSupport::TestCase |
| 1378 | 1386 | end |
| 1379 | 1387 | |
| 1380 | 1388 | should 'get only non translated articles' do |
| 1381 | - p = fast_create(Profile) | |
| 1382 | - native = fast_create(Article, :language => 'pt', :profile_id => p.id) | |
| 1383 | - translation = fast_create(Article, :language => 'en', :translation_of_id => native.id, :profile_id => p.id) | |
| 1384 | - assert_equal [native], p.articles.native_translations | |
| 1389 | + profile.articles.delete_all | |
| 1390 | + native = fast_create(Article, :language => 'pt', :profile_id => profile.id) | |
| 1391 | + translation = fast_create(Article, :language => 'en', :translation_of_id => native.id, :profile_id => profile.id) | |
| 1392 | + assert_equal [native], profile.articles.native_translations | |
| 1385 | 1393 | end |
| 1386 | 1394 | |
| 1387 | 1395 | should 'not list own language as a possible translation if language has changed' do |
| 1388 | - a = build(Article, :language => 'pt', :profile_id => fast_create(Profile).id) | |
| 1396 | + a = build(Article, :language => 'pt', :profile_id => profile.id) | |
| 1389 | 1397 | refute a.possible_translations.include?('pt') |
| 1390 | - a = fast_create(Article, :language => 'pt', :profile_id => fast_create(Profile).id ) | |
| 1398 | + a = fast_create(Article, :language => 'pt', :profile_id => profile.id ) | |
| 1391 | 1399 | a.language = 'en' |
| 1392 | 1400 | refute a.possible_translations.include?('en') |
| 1393 | 1401 | end |
| 1394 | 1402 | |
| 1395 | 1403 | should 'list own language as a possible translation if language has not changed' do |
| 1396 | - a = fast_create(Article, :language => 'pt', :profile_id => fast_create(Profile).id) | |
| 1404 | + a = fast_create(Article, :language => 'pt', :profile_id => profile.id) | |
| 1397 | 1405 | assert a.possible_translations.include?('pt') |
| 1398 | 1406 | end |
| 1399 | 1407 | |
| ... | ... | @@ -1435,7 +1443,6 @@ class ArticleTest < ActiveSupport::TestCase |
| 1435 | 1443 | should 'return only folders' do |
| 1436 | 1444 | not_folders = [RssFeed, TinyMceArticle, Event, TextileArticle] |
| 1437 | 1445 | folders = [Folder, Blog, Gallery, Forum] |
| 1438 | - profile = fast_create(Profile) | |
| 1439 | 1446 | |
| 1440 | 1447 | not_folders.each do |klass| |
| 1441 | 1448 | item = fast_create(klass) |
| ... | ... | @@ -1451,7 +1458,6 @@ class ArticleTest < ActiveSupport::TestCase |
| 1451 | 1458 | should 'return no folders' do |
| 1452 | 1459 | not_folders = [RssFeed, TinyMceArticle, Event, TextileArticle] |
| 1453 | 1460 | folders = [Folder, Blog, Gallery, Forum] |
| 1454 | - profile = fast_create(Profile) | |
| 1455 | 1461 | |
| 1456 | 1462 | not_folders.each do |klass| |
| 1457 | 1463 | item = fast_create(klass) |
| ... | ... | @@ -1611,18 +1617,16 @@ class ArticleTest < ActiveSupport::TestCase |
| 1611 | 1617 | end |
| 1612 | 1618 | |
| 1613 | 1619 | should 'delegate region info to profile' do |
| 1614 | - profile = fast_create(Profile) | |
| 1615 | - Profile.any_instance.expects(:region) | |
| 1616 | - Profile.any_instance.expects(:region_id) | |
| 1620 | + Person.any_instance.expects(:region) | |
| 1621 | + Person.any_instance.expects(:region_id) | |
| 1617 | 1622 | article = fast_create(Article, :profile_id => profile.id) |
| 1618 | 1623 | article.region |
| 1619 | 1624 | article.region_id |
| 1620 | 1625 | end |
| 1621 | 1626 | |
| 1622 | 1627 | should 'delegate environment info to profile' do |
| 1623 | - profile = fast_create(Profile) | |
| 1624 | - Profile.any_instance.expects(:environment) | |
| 1625 | - Profile.any_instance.expects(:environment_id) | |
| 1628 | + Person.any_instance.expects(:environment) | |
| 1629 | + Person.any_instance.expects(:environment_id) | |
| 1626 | 1630 | article = fast_create(Article, :profile_id => profile.id) |
| 1627 | 1631 | article.environment |
| 1628 | 1632 | article.environment_id |
| ... | ... | @@ -1711,7 +1715,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1711 | 1715 | |
| 1712 | 1716 | should 'has a empty list of followers by default' do |
| 1713 | 1717 | a = Article.new |
| 1714 | - assert_equal [], a.followers | |
| 1718 | + assert_equal [], a.person_followers | |
| 1715 | 1719 | end |
| 1716 | 1720 | |
| 1717 | 1721 | should 'get first image from lead' do |
| ... | ... | @@ -2229,6 +2233,14 @@ class ArticleTest < ActiveSupport::TestCase |
| 2229 | 2233 | end |
| 2230 | 2234 | end |
| 2231 | 2235 | |
| 2236 | + should 'be able to vote in an article without a user' do | |
| 2237 | + article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => nil) | |
| 2238 | + assert_difference 'article.votes_for', 2 do | |
| 2239 | + Vote.create!(:voteable => article, :vote => 1) | |
| 2240 | + Vote.create!(:voteable => article, :vote => 1) | |
| 2241 | + end | |
| 2242 | + end | |
| 2243 | + | |
| 2232 | 2244 | should 'have can_display_media_panel with default false' do |
| 2233 | 2245 | a = Article.new |
| 2234 | 2246 | assert !a.can_display_media_panel? |
| ... | ... | @@ -2278,4 +2290,15 @@ class ArticleTest < ActiveSupport::TestCase |
| 2278 | 2290 | assert_match 'Parent folder is archived', err.message |
| 2279 | 2291 | end |
| 2280 | 2292 | |
| 2293 | + should 'return full_path' do | |
| 2294 | + p1 = fast_create(Profile) | |
| 2295 | + p2 = fast_create(Profile) | |
| 2296 | + p2.domains << Domain.create!(:name => 'p2.domain') | |
| 2297 | + a1 = fast_create(Article, :profile_id => p1.id) | |
| 2298 | + a2 = fast_create(Article, :profile_id => p2.id) | |
| 2299 | + | |
| 2300 | + assert_equal "/#{p1.identifier}/#{a1.path}", a1.full_path | |
| 2301 | + assert_equal "/#{a2.path}", a2.full_path | |
| 2302 | + end | |
| 2303 | + | |
| 2281 | 2304 | end | ... | ... |
test/unit/blog_helper_test.rb
| ... | ... | @@ -101,11 +101,9 @@ class BlogHelperTest < ActionView::TestCase |
| 101 | 101 | |
| 102 | 102 | should 'display link to file if post is an uploaded_file' do |
| 103 | 103 | file = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => profile, :published => true, :parent => blog) |
| 104 | - | |
| 105 | 104 | result = display_post(file) |
| 106 | - assert_tag_in_string result, :tag => 'a', | |
| 107 | - :attributes => { :href => file.public_filename }, | |
| 108 | - :content => _('Download') | |
| 105 | + | |
| 106 | + assert_tag_in_string result, :tag => 'a', :content => _('Download') | |
| 109 | 107 | end |
| 110 | 108 | |
| 111 | 109 | should 'display image if post is an image' do | ... | ... |
test/unit/boxes_helper_test.rb
| ... | ... | @@ -187,6 +187,7 @@ class BoxesHelperTest < ActionView::TestCase |
| 187 | 187 | block = Block.create!(:box => box) |
| 188 | 188 | block.stubs(:embedable?).returns(true) |
| 189 | 189 | stubs(:url_for).returns('') |
| 190 | + @controller.stubs(:user).returns(box.owner) | |
| 190 | 191 | assert_tag_in_string block_edit_buttons(block), :tag => 'a', :attributes => {:class => 'button icon-button icon-embed '} |
| 191 | 192 | end |
| 192 | 193 | |
| ... | ... | @@ -195,6 +196,7 @@ class BoxesHelperTest < ActionView::TestCase |
| 195 | 196 | block = Block.create!(:box => box) |
| 196 | 197 | block.stubs(:embedable?).returns(false) |
| 197 | 198 | stubs(:url_for).returns('') |
| 199 | + @controller.stubs(:user).returns(box.owner) | |
| 198 | 200 | assert_no_tag_in_string block_edit_buttons(block), :tag => 'a', :attributes => {:class => 'button icon-button icon-embed '} |
| 199 | 201 | end |
| 200 | 202 | ... | ... |
test/unit/comment_notifier_test.rb
| ... | ... | @@ -60,7 +60,7 @@ class CommentNotifierTest < ActiveSupport::TestCase |
| 60 | 60 | should "deliver mail to followers" do |
| 61 | 61 | author = create_user('follower_author').person |
| 62 | 62 | follower = create_user('follower').person |
| 63 | - @article.followers += [follower.email] | |
| 63 | + @article.person_followers += [follower] | |
| 64 | 64 | @article.save! |
| 65 | 65 | create_comment_and_notify(:source => @article, :author => author, :title => 'comment title', :body => 'comment body') |
| 66 | 66 | assert_includes ActionMailer::Base.deliveries.map(&:bcc).flatten, follower.email | ... | ... |
test/unit/comment_test.rb
| ... | ... | @@ -339,34 +339,27 @@ class CommentTest < ActiveSupport::TestCase |
| 339 | 339 | assert c.rejected? |
| 340 | 340 | end |
| 341 | 341 | |
| 342 | - should 'subscribe user as follower of an article on new comment' do | |
| 342 | + should 'not subscribe user as follower of an article automatically on new comment' do | |
| 343 | 343 | owner = create_user('owner_of_article').person |
| 344 | 344 | person = create_user('follower').person |
| 345 | 345 | article = fast_create(Article, :profile_id => owner.id) |
| 346 | - assert_not_includes article.followers, person.email | |
| 346 | + assert_not_includes article.person_followers, person | |
| 347 | 347 | create(Comment, :source => article, :author => person, :title => 'new comment', :body => 'new comment') |
| 348 | - assert_includes article.reload.followers, person.email | |
| 348 | + assert_not_includes article.reload.person_followers, person | |
| 349 | 349 | end |
| 350 | 350 | |
| 351 | - should 'subscribe guest user as follower of an article on new comment' do | |
| 351 | + should 'not subscribe guest user as follower of an article on new comment' do | |
| 352 | 352 | article = fast_create(Article, :profile_id => create_user('article_owner').person.id) |
| 353 | - assert_not_includes article.followers, 'follower@example.com' | |
| 353 | + old_num_followers = article.reload.person_followers.size | |
| 354 | 354 | create(Comment, :source => article, :name => 'follower', :email => 'follower@example.com', :title => 'new comment', :body => 'new comment') |
| 355 | - assert_includes article.reload.followers, 'follower@example.com' | |
| 356 | - end | |
| 357 | - | |
| 358 | - should 'keep unique emails in list of followers' do | |
| 359 | - article = fast_create(Article, :profile_id => create_user('article_owner').person.id) | |
| 360 | - create(Comment, :source => article, :name => 'follower one', :email => 'follower@example.com', :title => 'new comment', :body => 'new comment') | |
| 361 | - create(Comment, :source => article, :name => 'follower two', :email => 'follower@example.com', :title => 'another comment', :body => 'new comment') | |
| 362 | - assert_equal 1, article.reload.followers.select{|v| v == 'follower@example.com'}.count | |
| 355 | + assert_equal old_num_followers, article.reload.person_followers.size | |
| 363 | 356 | end |
| 364 | 357 | |
| 365 | 358 | should 'not subscribe owner as follower of an article on new comment' do |
| 366 | 359 | owner = create_user('owner_of_article').person |
| 367 | 360 | article = fast_create(Article, :profile_id => owner.id) |
| 368 | 361 | create(Comment, :source => article, :author => owner, :title => 'new comment', :body => 'new comment') |
| 369 | - assert_not_includes article.reload.followers, owner.email | |
| 362 | + assert_not_includes article.reload.person_followers, owner | |
| 370 | 363 | end |
| 371 | 364 | |
| 372 | 365 | should 'not subscribe admins as follower of an article on new comment' do |
| ... | ... | @@ -377,8 +370,13 @@ class CommentTest < ActiveSupport::TestCase |
| 377 | 370 | article = fast_create(Article, :profile_id => owner.id) |
| 378 | 371 | create(Comment, :source => article, :author => follower, :title => 'new comment', :body => 'new comment') |
| 379 | 372 | create(Comment, :source => article, :author => admin, :title => 'new comment', :body => 'new comment') |
| 380 | - assert_not_includes article.reload.followers, admin.email | |
| 381 | - assert_includes article.followers, follower.email | |
| 373 | + | |
| 374 | + article.person_followers += [follower] | |
| 375 | + article.save! | |
| 376 | + article.reload | |
| 377 | + | |
| 378 | + assert_not_includes article.reload.person_followers, admin | |
| 379 | + assert_includes article.reload.person_followers, follower | |
| 382 | 380 | end |
| 383 | 381 | |
| 384 | 382 | should 'update article activity when add a comment' do | ... | ... |
test/unit/highlights_block_test.rb
| ... | ... | @@ -54,7 +54,19 @@ class HighlightsBlockTest < ActiveSupport::TestCase |
| 54 | 54 | should 'remove images with blank fields' do |
| 55 | 55 | h = HighlightsBlock.new(:images => [{:image_id => 1, :address => '/address', :position => 1, :title => 'address'}, {:image_id => '', :address => '', :position => '', :title => ''}]) |
| 56 | 56 | h.save! |
| 57 | - assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :image_src => nil}], h.images | |
| 57 | + assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :new_window => false, :image_src => nil}], h.images | |
| 58 | + end | |
| 59 | + | |
| 60 | + should 'replace 1 and 0 by true and false in new_window attribute' do | |
| 61 | + image1 = {:image_id => 1, :address => '/address-1', :position => 1, :title => 'address-1', :new_window => '0'} | |
| 62 | + image2 = {:image_id => 2, :address => '/address-2', :position => 2, :title => 'address-2', :new_window => '1'} | |
| 63 | + h = HighlightsBlock.new(:images => [image1, image2]) | |
| 64 | + h.save! | |
| 65 | + image1[:new_window] = false | |
| 66 | + image1[:image_src] = nil | |
| 67 | + image2[:new_window] = true | |
| 68 | + image2[:image_src] = nil | |
| 69 | + assert_equivalent [image1, image2], h.images | |
| 58 | 70 | end |
| 59 | 71 | |
| 60 | 72 | should 'be able to update display setting' do |
| ... | ... | @@ -84,7 +96,7 @@ class HighlightsBlockTest < ActiveSupport::TestCase |
| 84 | 96 | block.save! |
| 85 | 97 | block.reload |
| 86 | 98 | assert_equal 2, block.images.count |
| 87 | - assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :image_src => 'address'}], block.featured_images | |
| 99 | + assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :new_window => false, :image_src => 'address'}], block.featured_images | |
| 88 | 100 | end |
| 89 | 101 | |
| 90 | 102 | should 'list images in order' do | ... | ... |
test/unit/noosfero_test.rb
| ... | ... | @@ -21,6 +21,7 @@ class NoosferoTest < ActiveSupport::TestCase |
| 21 | 21 | should 'support setting default locale' do |
| 22 | 22 | Noosfero.default_locale = 'pt_BR' |
| 23 | 23 | assert_equal 'pt_BR', Noosfero.default_locale |
| 24 | + Noosfero.default_locale = nil | |
| 24 | 25 | end |
| 25 | 26 | |
| 26 | 27 | should 'identifier format' do | ... | ... |
test/unit/organization_mailing_test.rb
| ... | ... | @@ -98,6 +98,11 @@ class OrganizationMailingTest < ActiveSupport::TestCase |
| 98 | 98 | assert_equal [Person['user_one'], Person['user_two']], mailing.recipients |
| 99 | 99 | end |
| 100 | 100 | |
| 101 | + should 'return recipients previously filtered' do | |
| 102 | + mailing = create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person, :data => {:members_filtered => [Person['user_one'].id,Person['user_two'].id]}) | |
| 103 | + assert_equivalent [Person['user_one'], Person['user_two']], mailing.recipients | |
| 104 | + end | |
| 105 | + | |
| 101 | 106 | should 'return recipients according to limit' do |
| 102 | 107 | mailing = create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person) |
| 103 | 108 | assert_equal [Person['user_one']], mailing.recipients(0, 1) | ... | ... |
test/unit/person_notifier_test.rb
| ... | ... | @@ -49,7 +49,8 @@ class PersonNotifierTest < ActiveSupport::TestCase |
| 49 | 49 | should 'display author name in delivered mail' do |
| 50 | 50 | @community.add_member(@member) |
| 51 | 51 | User.current = @admin.user |
| 52 | - Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article) | |
| 52 | + comment = Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article) | |
| 53 | + comment.save! | |
| 53 | 54 | process_delayed_job_queue |
| 54 | 55 | notify |
| 55 | 56 | sent = ActionMailer::Base.deliveries.last | ... | ... |
test/unit/person_test.rb
| ... | ... | @@ -1845,4 +1845,100 @@ class PersonTest < ActiveSupport::TestCase |
| 1845 | 1845 | assert_equivalent [c1,c3], p1.comments |
| 1846 | 1846 | end |
| 1847 | 1847 | |
| 1848 | + should 'get people of one community by moderator role' do | |
| 1849 | + community = fast_create(Community) | |
| 1850 | + p1 = fast_create(Person) | |
| 1851 | + p2 = fast_create(Person) | |
| 1852 | + | |
| 1853 | + community.add_member p1 | |
| 1854 | + community.add_moderator p2 | |
| 1855 | + | |
| 1856 | + assert_equivalent [p2], Person.with_role(Profile::Roles.moderator(community.environment.id).id) | |
| 1857 | + end | |
| 1858 | + | |
| 1859 | + should 'get people of one community by admin role' do | |
| 1860 | + community = fast_create(Community) | |
| 1861 | + p1 = fast_create(Person) | |
| 1862 | + p2 = fast_create(Person) | |
| 1863 | + | |
| 1864 | + community.add_admin p1 | |
| 1865 | + community.add_member p2 | |
| 1866 | + | |
| 1867 | + assert_equivalent [p1], Person.with_role(Profile::Roles.admin(community.environment.id).id) | |
| 1868 | + end | |
| 1869 | + | |
| 1870 | + should 'get people with admin role of any community' do | |
| 1871 | + c1 = fast_create(Community) | |
| 1872 | + p1 = fast_create(Person) | |
| 1873 | + p2 = fast_create(Person) | |
| 1874 | + c1.add_admin p1 | |
| 1875 | + c1.add_member p2 | |
| 1876 | + | |
| 1877 | + c2 = fast_create(Community) | |
| 1878 | + p3 = fast_create(Person) | |
| 1879 | + p4 = fast_create(Person) | |
| 1880 | + | |
| 1881 | + c2.add_admin p4 | |
| 1882 | + c2.add_member p3 | |
| 1883 | + | |
| 1884 | + assert_equivalent [p1, p4], Person.with_role(Profile::Roles.admin(c1.environment.id).id) | |
| 1885 | + end | |
| 1886 | + | |
| 1887 | + should 'get distinct people with moderator role of any community' do | |
| 1888 | + c1 = fast_create(Community) | |
| 1889 | + p1 = fast_create(Person) | |
| 1890 | + p2 = fast_create(Person) | |
| 1891 | + c1.add_member p1 | |
| 1892 | + c1.add_moderator p2 | |
| 1893 | + | |
| 1894 | + c2 = fast_create(Community) | |
| 1895 | + p3 = fast_create(Person) | |
| 1896 | + p4 = fast_create(Person) | |
| 1897 | + | |
| 1898 | + c2.add_member p4 | |
| 1899 | + c2.add_moderator p3 | |
| 1900 | + c2.add_moderator p2 | |
| 1901 | + | |
| 1902 | + assert_equivalent [p2, p3], Person.with_role(Profile::Roles.moderator(c1.environment.id).id) | |
| 1903 | + end | |
| 1904 | + | |
| 1905 | + should 'count members of a community collected by moderator' do | |
| 1906 | + c1 = fast_create(Community) | |
| 1907 | + p1 = fast_create(Person) | |
| 1908 | + p2 = fast_create(Person) | |
| 1909 | + p3 = fast_create(Person) | |
| 1910 | + c1.add_member p1 | |
| 1911 | + c1.add_moderator p2 | |
| 1912 | + c1.add_member p3 | |
| 1913 | + | |
| 1914 | + assert_equal 1, c1.members.with_role(Profile::Roles.moderator(c1.environment.id).id).count | |
| 1915 | + end | |
| 1916 | + | |
| 1917 | + should 'count people of any community collected by moderator' do | |
| 1918 | + c1 = fast_create(Community) | |
| 1919 | + p1 = fast_create(Person) | |
| 1920 | + p2 = fast_create(Person) | |
| 1921 | + c1.add_member p1 | |
| 1922 | + c1.add_moderator p2 | |
| 1923 | + | |
| 1924 | + c2 = fast_create(Community) | |
| 1925 | + p3 = fast_create(Person) | |
| 1926 | + p4 = fast_create(Person) | |
| 1927 | + | |
| 1928 | + c2.add_member p4 | |
| 1929 | + c2.add_moderator p3 | |
| 1930 | + c2.add_moderator p2 | |
| 1931 | + | |
| 1932 | + assert_equal 2, Person.with_role(Profile::Roles.moderator(c1.environment.id).id).count | |
| 1933 | + end | |
| 1934 | + | |
| 1935 | + should 'check if a person is added like a member of a community today' do | |
| 1936 | + person = create_user('person').person | |
| 1937 | + community = fast_create(Community) | |
| 1938 | + | |
| 1939 | + community.add_member person | |
| 1940 | + | |
| 1941 | + assert !person.member_relation_of(community).empty?, "Person '#{person.identifier}' is not a member of Community '#{community.identifier}'" | |
| 1942 | + assert person.member_since_date(community) == Date.today,"Person '#{person.identifier}' is not added like a member of Community '#{community.identifier}' today" | |
| 1943 | + end | |
| 1848 | 1944 | end | ... | ... |
test/unit/profile_test.rb
| ... | ... | @@ -1816,6 +1816,21 @@ class ProfileTest < ActiveSupport::TestCase |
| 1816 | 1816 | assert_equal [person], community.members |
| 1817 | 1817 | end |
| 1818 | 1818 | |
| 1819 | + should 'return a list members by email of a community' do | |
| 1820 | + someone = create_user('Someone', email:'someone@test.com.br') | |
| 1821 | + someperson = create_user('Someperson',email:'someperson@test.com.br') | |
| 1822 | + | |
| 1823 | + community = fast_create(Community) | |
| 1824 | + community.add_member(someone.person) | |
| 1825 | + community.add_member(someperson.person) | |
| 1826 | + | |
| 1827 | + result = community.members_like 'email', '@test.com.br' | |
| 1828 | + | |
| 1829 | + assert_includes result, someone.person | |
| 1830 | + assert_includes result, someperson.person | |
| 1831 | + | |
| 1832 | + end | |
| 1833 | + | |
| 1819 | 1834 | should 'count unique members of a community' do |
| 1820 | 1835 | person = fast_create(Person) |
| 1821 | 1836 | community = fast_create(Community) | ... | ... |
test/unit/raw_html_block_test.rb
| ... | ... | @@ -22,4 +22,20 @@ class RawHTMLBlockTest < ActiveSupport::TestCase |
| 22 | 22 | assert_match(/HTML$/, block.content) |
| 23 | 23 | end |
| 24 | 24 | |
| 25 | + should 'not be editable for users without permission' do | |
| 26 | + environment = Environment.default | |
| 27 | + box = Box.new(:owner => environment) | |
| 28 | + block = RawHTMLBlock.new(:html => "HTML", :box => box) | |
| 29 | + user = create_user('testuser').person | |
| 30 | + assert !block.editable?(user) | |
| 31 | + end | |
| 32 | + | |
| 33 | + should 'be editable for users with permission' do | |
| 34 | + environment = Environment.default | |
| 35 | + box = Box.new(:owner => environment) | |
| 36 | + block = RawHTMLBlock.new(:html => "HTML", :box => box) | |
| 37 | + user = create_user_with_permission('testuser', 'edit_raw_html_block', environment) | |
| 38 | + assert block.editable?(user) | |
| 39 | + end | |
| 40 | + | |
| 25 | 41 | end | ... | ... |
test/unit/uploaded_file_test.rb
| ... | ... | @@ -357,4 +357,25 @@ class UploadedFileTest < ActiveSupport::TestCase |
| 357 | 357 | assert_instance_of Fixnum, UploadedFile.max_size |
| 358 | 358 | end |
| 359 | 359 | |
| 360 | + should 'add file to dbm if it becomes private' do | |
| 361 | + require 'sdbm' | |
| 362 | + public_file = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => profile, :published => true) | |
| 363 | + private_file = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile, :published => false) | |
| 364 | + | |
| 365 | + dbm = SDBM.open(UploadedFile::DBM_PRIVATE_FILE) | |
| 366 | + assert !dbm.has_key?(public_file.public_filename) | |
| 367 | + assert dbm.has_key?(private_file.public_filename) | |
| 368 | + dbm.close | |
| 369 | + | |
| 370 | + public_file.published = false | |
| 371 | + public_file.save! | |
| 372 | + private_file.published = true | |
| 373 | + private_file.save! | |
| 374 | + | |
| 375 | + dbm = SDBM.open(UploadedFile::DBM_PRIVATE_FILE) | |
| 376 | + assert dbm.has_key?(public_file.public_filename) | |
| 377 | + assert !dbm.has_key?(private_file.public_filename) | |
| 378 | + dbm.close | |
| 379 | + end | |
| 380 | + | |
| 360 | 381 | end | ... | ... |
util/chat/apache/xmpp.conf
| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | -# If your XMPP XMPP/BOSH isn't in localhost, change the config below to correct | |
| 2 | -# point to address | |
| 3 | - | |
| 4 | - RewriteEngine On | |
| 5 | - RewriteRule /http-bind http://localhost:5280/http-bind [P,QSA,L] | |
| 6 | - <Proxy http://localhost:5280/http-bind> | |
| 7 | - Order Allow,Deny | |
| 8 | - Allow from All | |
| 9 | - </Proxy> | |
| 10 | - | |
| 11 | -# vim: ft=apache |
vendor/plugins/access_control/lib/acts_as_accessible.rb
| ... | ... | @@ -19,9 +19,9 @@ module ActsAsAccessible |
| 19 | 19 | nil |
| 20 | 20 | end |
| 21 | 21 | |
| 22 | - def affiliate(accessor, roles) | |
| 22 | + def affiliate(accessor, roles, attributes = {}) | |
| 23 | 23 | roles = Array(roles) |
| 24 | - roles.map {|role| accessor.add_role(role, self)}.any? | |
| 24 | + roles.map {|role| accessor.add_role(role, self, attributes)}.any? | |
| 25 | 25 | end |
| 26 | 26 | |
| 27 | 27 | def disaffiliate(accessor, roles) | ... | ... |
vendor/plugins/access_control/lib/acts_as_accessor.rb
| ... | ... | @@ -21,9 +21,9 @@ module ActsAsAccessor |
| 21 | 21 | (actual_roles - roles).each {|r| remove_role(r, resource)} |
| 22 | 22 | end |
| 23 | 23 | |
| 24 | - def add_role(role, resource) | |
| 25 | - attributes = role_attributes(role, resource) | |
| 26 | - if RoleAssignment.where(attributes).empty? | |
| 24 | + def add_role(role, resource, attributes = {}) | |
| 25 | + attributes = role_attributes(role, resource).merge attributes | |
| 26 | + if RoleAssignment.find(:all, :conditions => attributes).empty? | |
| 27 | 27 | ra = RoleAssignment.new(attributes) |
| 28 | 28 | role_assignments << ra |
| 29 | 29 | resource.role_assignments << ra |
| ... | ... | @@ -44,6 +44,19 @@ module ActsAsAccessor |
| 44 | 44 | RoleAssignment.where(role_attributes nil, res) |
| 45 | 45 | end |
| 46 | 46 | |
| 47 | + def member_relation_of(profile) | |
| 48 | + raise TypeError, "Expected instance of 'Profile' class, but '#{profile.class.name}' was founded" unless profile.is_a? Profile | |
| 49 | + | |
| 50 | + role_assignments.where(resource_id: profile.id) | |
| 51 | + end | |
| 52 | + | |
| 53 | + def member_since_date(profile) | |
| 54 | + result = member_relation_of(profile).to_a | |
| 55 | + unless result.empty? | |
| 56 | + result.last.created_at ? result.last.created_at.to_date : Date.yesterday | |
| 57 | + end | |
| 58 | + end | |
| 59 | + | |
| 47 | 60 | protected |
| 48 | 61 | def role_attributes(role, resource) |
| 49 | 62 | attributes = {:accessor_id => self.id, :accessor_type => self.class.base_class.name} | ... | ... |
vendor/plugins/access_control/lib/role_assignment.rb
| 1 | 1 | class RoleAssignment < ActiveRecord::Base |
| 2 | 2 | |
| 3 | - attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type | |
| 3 | + attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type, :created_at | |
| 4 | 4 | |
| 5 | 5 | belongs_to :role |
| 6 | 6 | belongs_to :accessor, :polymorphic => true | ... | ... |