Commit b8a9f0b933ba576b6c4f08de68ea06d95ea83c71

Authored by Leandro Santos
2 parents cb32bc3f 4bfa4aaa
Exists in staging and in 1 other branch production

merge with master

app/api/entities.rb
@@ -111,6 +111,10 @@ module Api @@ -111,6 +111,10 @@ module Api
111 hash[value.custom_field.name]=value.value 111 hash[value.custom_field.name]=value.value
112 end 112 end
113 113
  114 + profile.public_fields.each do |field|
  115 + hash[field] = profile.send(field.to_sym)
  116 + end
  117 +
114 private_values = profile.custom_field_values - profile.public_values 118 private_values = profile.custom_field_values - profile.public_values
115 private_values.each do |value| 119 private_values.each do |value|
116 if Entities.can_display_profile_field?(profile,options) 120 if Entities.can_display_profile_field?(profile,options)
@@ -259,6 +263,14 @@ module Api @@ -259,6 +263,14 @@ module Api
259 root 'tasks', 'task' 263 root 'tasks', 'task'
260 expose :id 264 expose :id
261 expose :type 265 expose :type
  266 + expose :requestor, using: Profile
  267 + expose :status
  268 + expose :created_at
  269 + expose :data
  270 + expose :target do |task, options|
  271 + type_map = {Profile => ::Profile, Environment => ::Environment}.find {|h| task.target.kind_of?(h.last)}
  272 + type_map.first.represent(task.target) unless type_map.nil?
  273 + end
262 end 274 end
263 275
264 class Environment < Entity 276 class Environment < Entity
@@ -266,6 +278,9 @@ module Api @@ -266,6 +278,9 @@ module Api
266 expose :id 278 expose :id
267 expose :description 279 expose :description
268 expose :layout_template 280 expose :layout_template
  281 + expose :signup_intro
  282 + expose :terms_of_use
  283 + expose :top_url, as: :host
269 expose :settings, if: lambda { |instance, options| options[:is_admin] } 284 expose :settings, if: lambda { |instance, options| options[:is_admin] }
270 end 285 end
271 286
app/api/helpers.rb
@@ -4,7 +4,7 @@ require &#39;tempfile&#39; @@ -4,7 +4,7 @@ require &#39;tempfile&#39;
4 module Api 4 module Api
5 module Helpers 5 module Helpers
6 PRIVATE_TOKEN_PARAM = :private_token 6 PRIVATE_TOKEN_PARAM = :private_token
7 - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived] 7 + ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived, :status]
8 8
9 include SanitizeParams 9 include SanitizeParams
10 include Noosfero::Plugin::HotSpot 10 include Noosfero::Plugin::HotSpot
@@ -135,8 +135,8 @@ module Api @@ -135,8 +135,8 @@ module Api
135 present_partial article, with: Entities::Article, params: params, current_person: current_person 135 present_partial article, with: Entities::Article, params: params, current_person: current_person
136 end 136 end
137 137
138 - def present_articles_for_asset(asset, method = 'articles')  
139 - articles = find_articles(asset, method) 138 + def present_articles_for_asset(asset, method_or_relation = 'articles')
  139 + articles = find_articles(asset, method_or_relation)
140 present_articles(articles) 140 present_articles(articles)
141 end 141 end
142 142
@@ -144,8 +144,8 @@ module Api @@ -144,8 +144,8 @@ module Api
144 present_partial paginate(articles), :with => Entities::Article, :params => params, current_person: current_person 144 present_partial paginate(articles), :with => Entities::Article, :params => params, current_person: current_person
145 end 145 end
146 146
147 - def find_articles(asset, method = 'articles')  
148 - articles = select_filtered_collection_of(asset, method, params) 147 + def find_articles(asset, method_or_relation = 'articles')
  148 + articles = select_filtered_collection_of(asset, method_or_relation, params)
149 if current_person.present? 149 if current_person.present?
150 articles = articles.display_filter(current_person, nil) 150 articles = articles.display_filter(current_person, nil)
151 else 151 else
@@ -154,14 +154,17 @@ module Api @@ -154,14 +154,17 @@ module Api
154 articles 154 articles
155 end 155 end
156 156
157 - def find_task(asset, id)  
158 - task = asset.tasks.find(id) 157 + def find_task(asset, method_or_relation, id)
  158 + task = is_a_relation?(method_or_relation) ? method_or_relation : asset.send(method_or_relation)
  159 + task = task.find_by_id(id)
  160 + not_found! if task.blank?
159 current_person.has_permission?(task.permission, asset) ? task : forbidden! 161 current_person.has_permission?(task.permission, asset) ? task : forbidden!
160 end 162 end
161 163
162 def post_task(asset, params) 164 def post_task(asset, params)
163 klass_type= params[:content_type].nil? ? 'Task' : params[:content_type] 165 klass_type= params[:content_type].nil? ? 'Task' : params[:content_type]
164 return forbidden! unless klass_type.constantize <= Task 166 return forbidden! unless klass_type.constantize <= Task
  167 + return forbidden! if !current_person.has_permission?(:perform_task, asset)
165 168
166 task = klass_type.constantize.new(params[:task]) 169 task = klass_type.constantize.new(params[:task])
167 task.requestor_id = current_person.id 170 task.requestor_id = current_person.id
@@ -174,15 +177,24 @@ module Api @@ -174,15 +177,24 @@ module Api
174 present_partial task, :with => Entities::Task 177 present_partial task, :with => Entities::Task
175 end 178 end
176 179
177 - def present_task(asset)  
178 - task = find_task(asset, params[:id]) 180 + def find_tasks(asset, method_or_relation = 'tasks')
  181 + return forbidden! if !current_person.has_permission?(:perform_task, asset)
  182 + tasks = select_filtered_collection_of(asset, method_or_relation, params)
  183 + tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}
  184 + tasks
  185 + end
  186 +
  187 + def present_task(asset, method_or_relation = 'tasks')
  188 + task = find_task(asset, method_or_relation, params[:id])
179 present_partial task, :with => Entities::Task 189 present_partial task, :with => Entities::Task
180 end 190 end
181 191
182 - def present_tasks(asset)  
183 - tasks = select_filtered_collection_of(asset, 'tasks', params)  
184 - tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}  
185 - return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) 192 + def present_tasks_for_asset(asset, method_or_relation = 'tasks')
  193 + tasks = find_tasks(asset, method_or_relation)
  194 + present_tasks(tasks)
  195 + end
  196 +
  197 + def present_tasks(tasks)
186 present_partial tasks, :with => Entities::Task 198 present_partial tasks, :with => Entities::Task
187 end 199 end
188 200
@@ -191,7 +203,6 @@ module Api @@ -191,7 +203,6 @@ module Api
191 conditions = {} 203 conditions = {}
192 from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from] 204 from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from]
193 until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until] 205 until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until]
194 -  
195 conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil? 206 conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil?
196 207
197 conditions[:created_at] = period(from_date, until_date) if from_date || until_date 208 conditions[:created_at] = period(from_date, until_date) if from_date || until_date
@@ -201,7 +212,7 @@ module Api @@ -201,7 +212,7 @@ module Api
201 end 212 end
202 213
203 # changing make_order_with_parameters to avoid sql injection 214 # changing make_order_with_parameters to avoid sql injection
204 - def make_order_with_parameters(object, method, params) 215 + def make_order_with_parameters(object, method_or_relation, params)
205 order = "created_at DESC" 216 order = "created_at DESC"
206 unless params[:order].blank? 217 unless params[:order].blank?
207 if params[:order].include? '\'' or params[:order].include? '"' 218 if params[:order].include? '\'' or params[:order].include? '"'
@@ -210,9 +221,9 @@ module Api @@ -210,9 +221,9 @@ module Api
210 order = 'RANDOM()' 221 order = 'RANDOM()'
211 else 222 else
212 field_name, direction = params[:order].split(' ') 223 field_name, direction = params[:order].split(' ')
213 - assoc = object.class.reflect_on_association(method.to_sym)  
214 - if !field_name.blank? and assoc  
215 - if assoc.klass.attribute_names.include? field_name 224 + assoc_class = extract_associated_classname(method_or_relation)
  225 + if !field_name.blank? and assoc_class
  226 + if assoc_class.attribute_names.include? field_name
216 if direction.present? and ['ASC','DESC'].include? direction.upcase 227 if direction.present? and ['ASC','DESC'].include? direction.upcase
217 order = "#{field_name} #{direction.upcase}" 228 order = "#{field_name} #{direction.upcase}"
218 end 229 end
@@ -223,12 +234,14 @@ module Api @@ -223,12 +234,14 @@ module Api
223 return order 234 return order
224 end 235 end
225 236
226 - def make_timestamp_with_parameters_and_method(params, method) 237 + def make_timestamp_with_parameters_and_method(params, method_or_relation)
227 timestamp = nil 238 timestamp = nil
228 if params[:timestamp] 239 if params[:timestamp]
229 datetime = DateTime.parse(params[:timestamp]) 240 datetime = DateTime.parse(params[:timestamp])
230 - table_name = method.to_s.singularize.camelize.constantize.table_name  
231 - timestamp = "#{table_name}.updated_at >= '#{datetime}'" 241 + table_name = extract_associated_tablename(method_or_relation)
  242 + assoc_class = extract_associated_classname(method_or_relation)
  243 + date_atrr = assoc_class.attribute_names.include?('updated_at') ? 'updated_at' : 'created_at'
  244 + timestamp = "#{table_name}.#{date_atrr} >= '#{datetime}'"
232 end 245 end
233 246
234 timestamp 247 timestamp
@@ -263,12 +276,12 @@ module Api @@ -263,12 +276,12 @@ module Api
263 scope 276 scope
264 end 277 end
265 278
266 - def select_filtered_collection_of(object, method, params) 279 + def select_filtered_collection_of(object, method_or_relation, params)
267 conditions = make_conditions_with_parameter(params) 280 conditions = make_conditions_with_parameter(params)
268 - order = make_order_with_parameters(object,method,params)  
269 - timestamp = make_timestamp_with_parameters_and_method(params, method) 281 + order = make_order_with_parameters(object,method_or_relation,params)
  282 + timestamp = make_timestamp_with_parameters_and_method(params, method_or_relation)
270 283
271 - objects = object.send(method) 284 + objects = is_a_relation?(method_or_relation) ? method_or_relation : object.send(method_or_relation)
272 objects = by_reference(objects, params) 285 objects = by_reference(objects, params)
273 objects = by_categories(objects, params) 286 objects = by_categories(objects, params)
274 [:start_date, :end_date].each { |attribute| objects = by_period(objects, params, attribute) } 287 [:start_date, :end_date].each { |attribute| objects = by_period(objects, params, attribute) }
@@ -437,10 +450,27 @@ module Api @@ -437,10 +450,27 @@ module Api
437 end 450 end
438 private 451 private
439 452
  453 + def extract_associated_tablename(method_or_relation)
  454 + extract_associated_classname(method_or_relation).table_name
  455 + end
  456 +
  457 + def extract_associated_classname(method_or_relation)
  458 + if is_a_relation?(method_or_relation)
  459 + method_or_relation.blank? ? '' : method_or_relation.first.class
  460 + else
  461 + method_or_relation.to_s.singularize.camelize.constantize
  462 + end
  463 + end
  464 +
  465 + def is_a_relation?(method_or_relation)
  466 + method_or_relation.kind_of?(ActiveRecord::Relation)
  467 + end
  468 +
  469 +
440 def parser_params(params) 470 def parser_params(params)
441 parsed_params = {} 471 parsed_params = {}
442 params.map do |k,v| 472 params.map do |k,v|
443 - parsed_params[k.to_sym] = v if DEFAULT_ALLOWED_PARAMETERS.include?(k.to_sym) 473 + parsed_params[k.to_sym] = v if ALLOWED_PARAMETERS.include?(k.to_sym)
444 end 474 end
445 parsed_params 475 parsed_params
446 end 476 end
app/api/v1/tasks.rb
1 module Api 1 module Api
2 module V1 2 module V1
3 class Tasks < Grape::API 3 class Tasks < Grape::API
4 -# before { authenticate! } 4 + before { authenticate! }
5 5
6 -# ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} 6 + MAX_PER_PAGE = 50
7 7
8 resource :tasks do 8 resource :tasks do
9 9
10 - # Collect tasks 10 + paginate max_per_page: MAX_PER_PAGE
  11 + # Collect all tasks that current person has permission
11 # 12 #
12 # Parameters: 13 # Parameters:
13 # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created 14 # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created
@@ -17,15 +18,22 @@ module Api @@ -17,15 +18,22 @@ module Api
17 # Example Request: 18 # Example Request:
18 # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 19 # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317
19 get do 20 get do
20 - tasks = select_filtered_collection_of(environment, 'tasks', params)  
21 - tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)}  
22 - present_partial tasks, :with => Entities::Task 21 + tasks = Task.to(current_person)
  22 + present_tasks_for_asset(current_person, tasks)
23 end 23 end
24 24
25 desc "Return the task id" 25 desc "Return the task id"
26 get ':id' do 26 get ':id' do
27 - task = find_task(environment, params[:id])  
28 - present_partial task, :with => Entities::Task 27 + present_task(current_person, Task.to(current_person))
  28 + end
  29 +
  30 + %w[finish cancel].each do |action|
  31 + desc "#{action.capitalize} a task"
  32 + put ":id/#{action}" do
  33 + task = find_task(current_person, Task.to(current_person), params[:id])
  34 + task.send(action, current_person) if (task.status == Task::Status::ACTIVE)
  35 + present_partial task, :with => Entities::Task
  36 + end
29 end 37 end
30 end 38 end
31 39
@@ -36,7 +44,8 @@ module Api @@ -36,7 +44,8 @@ module Api
36 resource :tasks do 44 resource :tasks do
37 get do 45 get do
38 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 46 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
39 - present_tasks(profile) 47 + tasks = Task.to(profile)
  48 + present_tasks_for_asset(profile, tasks)
40 end 49 end
41 50
42 get ':id' do 51 get ':id' do
app/controllers/my_profile/tasks_controller.rb
@@ -18,7 +18,7 @@ class TasksController &lt; MyProfileController @@ -18,7 +18,7 @@ class TasksController &lt; MyProfileController
18 @task_types = Task.pending_types_for(profile) 18 @task_types = Task.pending_types_for(profile)
19 @task_tags = [OpenStruct.new(:name => _('All'), :id => nil) ] + Task.all_tags 19 @task_tags = [OpenStruct.new(:name => _('All'), :id => nil) ] + Task.all_tags
20 20
21 - @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) 21 + @tasks = Task.pending_all_by_filter(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page])
22 @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? 22 @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present?
23 @tasks = @tasks.tagged_with(@filter_tags, any: true) if @filter_tags.present? 23 @tasks = @tasks.tagged_with(@filter_tags, any: true) if @filter_tags.present?
24 @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) 24 @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
@@ -121,7 +121,7 @@ class TasksController &lt; MyProfileController @@ -121,7 +121,7 @@ class TasksController &lt; MyProfileController
121 def search_tasks 121 def search_tasks
122 filter_type = params[:filter_type].presence 122 filter_type = params[:filter_type].presence
123 filter_text = params[:filter_text].presence 123 filter_text = params[:filter_text].presence
124 - result = Task.pending_all(profile,filter_type, filter_text) 124 + result = Task.pending_all_by_filter(profile,filter_type, filter_text)
125 125
126 render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} } 126 render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} }
127 end 127 end
app/helpers/boxes_helper.rb
@@ -285,7 +285,7 @@ module BoxesHelper @@ -285,7 +285,7 @@ module BoxesHelper
285 end 285 end
286 286
287 if block.respond_to?(:help) 287 if block.respond_to?(:help)
288 - buttons << modal_inline_icon(:help, _('Help on this block'), {}, "#help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + modal_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}") 288 + buttons << modal_inline_icon(:help, _('Help on this block'), {}, "#help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help.html_safe, :style => 'margin-bottom: 1em;') + modal_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}")
289 end 289 end
290 290
291 if block.embedable? 291 if block.embedable?
app/models/task.rb
@@ -337,7 +337,7 @@ class Task &lt; ApplicationRecord @@ -337,7 +337,7 @@ class Task &lt; ApplicationRecord
337 where "LOWER(#{field}) LIKE ?", "%#{value.downcase}%" 337 where "LOWER(#{field}) LIKE ?", "%#{value.downcase}%"
338 end 338 end
339 } 339 }
340 - scope :pending_all, -> profile, filter_type, filter_text { 340 + scope :pending_all_by_filter, -> profile, filter_type, filter_text {
341 self.to(profile).without_spam.pending.of(filter_type).like('data', filter_text) 341 self.to(profile).without_spam.pending.of(filter_type).like('data', filter_text)
342 } 342 }
343 343
@@ -346,10 +346,17 @@ class Task &lt; ApplicationRecord @@ -346,10 +346,17 @@ class Task &lt; ApplicationRecord
346 if profile.person? 346 if profile.person?
347 envs_ids = Environment.all.select{ |env| profile.is_admin?(env) }.map{ |env| "target_id = #{env.id}"}.join(' OR ') 347 envs_ids = Environment.all.select{ |env| profile.is_admin?(env) }.map{ |env| "target_id = #{env.id}"}.join(' OR ')
348 environment_condition = envs_ids.blank? ? nil : "(target_type = 'Environment' AND (#{envs_ids}))" 348 environment_condition = envs_ids.blank? ? nil : "(target_type = 'Environment' AND (#{envs_ids}))"
  349 +
  350 + organizations = profile.memberships.all.select do |organization|
  351 + profile.has_permission?(:perform_task, organization)
  352 + end
  353 + organization_ids = organizations.map{ |organization| "target_id = #{organization.id}"}.join(' OR ')
  354 +
  355 + organization_conditions = organization_ids.blank? ? nil : "(target_type = 'Profile' AND (#{organization_ids}))"
349 end 356 end
350 profile_condition = "(target_type = 'Profile' AND target_id = #{profile.id})" 357 profile_condition = "(target_type = 'Profile' AND target_id = #{profile.id})"
351 358
352 - where [environment_condition, profile_condition].compact.join(' OR ') 359 + where [environment_condition, organization_conditions, profile_condition].compact.join(' OR ')
353 } 360 }
354 361
355 scope :from_closed_date, -> closed_from { 362 scope :from_closed_date, -> closed_from {
app/views/box_organizer/show_block_type_info.html.erb
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 <div id="block-info-description"> 15 <div id="block-info-description">
16 <h2><%= _('Description') %></h2> 16 <h2><%= _('Description') %></h2>
17 <p><%= @block.class.description %></p> 17 <p><%= @block.class.description %></p>
18 - <p><%= @block.help if @block.class.method_defined?(:help) %></p> 18 + <p><%= @block.help.html_safe if @block.class.method_defined?(:help) %></p>
19 </div> 19 </div>
20 20
21 </div> 21 </div>
plugins/proposals_discussion
1 -Subproject commit dabe481afb873d2e409a03f1b83bfbc849027f44 1 +Subproject commit 3d50338b0fee72107cb18b5a93f3c051c4ff31d9
test/api/profiles_test.rb
@@ -123,6 +123,24 @@ class ProfilesTest &lt; ActiveSupport::TestCase @@ -123,6 +123,24 @@ class ProfilesTest &lt; ActiveSupport::TestCase
123 assert_equal community.id, json['id'] 123 assert_equal community.id, json['id']
124 end 124 end
125 125
  126 + should 'display profile public fields to anonymous' do
  127 + some_person = create_user('test', { :email => "lappis@unb.br" }).person
  128 + Person.any_instance.stubs(:public_fields).returns(["email"])
  129 +
  130 + get "/api/v1/profiles/#{some_person.id}?#{params.to_query}"
  131 + json = JSON.parse(last_response.body)
  132 + assert json['additional_data'].has_key?('email')
  133 + assert_equal "lappis@unb.br", json['additional_data']['email']
  134 + end
  135 +
  136 + should 'not display private fields to anonymous' do
  137 + some_person = create_user('test', { :email => "lappis@unb.br" }).person
  138 +
  139 + get "/api/v1/profiles/#{some_person.id}/?#{params.to_query}"
  140 + json = JSON.parse(last_response.body)
  141 + assert !json['additional_data'].has_key?('email')
  142 + end
  143 +
126 should 'display public custom fields to anonymous' do 144 should 'display public custom fields to anonymous' do
127 CustomField.create!(:name => "Rating", :format => "string", :customized_type => "Profile", :active => true, :environment => Environment.default) 145 CustomField.create!(:name => "Rating", :format => "string", :customized_type => "Profile", :active => true, :environment => Environment.default)
128 some_profile = fast_create(Profile) 146 some_profile = fast_create(Profile)
test/api/task_test.rb
@@ -11,7 +11,7 @@ class TasksTest &lt; ActiveSupport::TestCase @@ -11,7 +11,7 @@ class TasksTest &lt; ActiveSupport::TestCase
11 11
12 attr_accessor :person, :community, :environment 12 attr_accessor :person, :community, :environment
13 13
14 - should 'list tasks of environment' do 14 + should 'list environment tasks for admin user' do
15 environment.add_admin(person) 15 environment.add_admin(person)
16 task = create(Task, :requestor => person, :target => environment) 16 task = create(Task, :requestor => person, :target => environment)
17 get "/api/v1/tasks?#{params.to_query}" 17 get "/api/v1/tasks?#{params.to_query}"
@@ -19,6 +19,15 @@ class TasksTest &lt; ActiveSupport::TestCase @@ -19,6 +19,15 @@ class TasksTest &lt; ActiveSupport::TestCase
19 assert_includes json["tasks"].map { |a| a["id"] }, task.id 19 assert_includes json["tasks"].map { |a| a["id"] }, task.id
20 end 20 end
21 21
  22 + should 'not list tasks of environment for unlogged users' do
  23 + logout_api
  24 + environment.add_admin(person)
  25 + task = create(Task, :requestor => person, :target => environment)
  26 + get "/api/v1/tasks?#{params.to_query}"
  27 + json = JSON.parse(last_response.body)
  28 + assert_equal 401, last_response.status
  29 + end
  30 +
22 should 'return environment task by id' do 31 should 'return environment task by id' do
23 environment.add_admin(person) 32 environment.add_admin(person)
24 task = create(Task, :requestor => person, :target => environment) 33 task = create(Task, :requestor => person, :target => environment)
@@ -27,147 +36,290 @@ class TasksTest &lt; ActiveSupport::TestCase @@ -27,147 +36,290 @@ class TasksTest &lt; ActiveSupport::TestCase
27 assert_equal task.id, json["task"]["id"] 36 assert_equal task.id, json["task"]["id"]
28 end 37 end
29 38
  39 + should 'not return environment task by id for unlogged users' do
  40 + logout_api
  41 + environment.add_admin(person)
  42 + task = create(Task, :requestor => person, :target => environment)
  43 + get "/api/v1/tasks/#{task.id}?#{params.to_query}"
  44 + json = JSON.parse(last_response.body)
  45 + assert_equal 401, last_response.status
  46 + end
  47 +
30 should 'not return environmet task if user has no permission to view it' do 48 should 'not return environmet task if user has no permission to view it' do
31 person = fast_create(Person) 49 person = fast_create(Person)
32 task = create(Task, :requestor => person, :target => environment) 50 task = create(Task, :requestor => person, :target => environment)
33 51
34 get "/api/v1/tasks/#{task.id}?#{params.to_query}" 52 get "/api/v1/tasks/#{task.id}?#{params.to_query}"
35 - assert_equal 403, last_response.status 53 + assert_equal 404, last_response.status
36 end 54 end
37 55
38 - #############################  
39 - # Community Tasks #  
40 - ############################# 56 + should 'find the current user task even it is finished' do
  57 + t3 = create(Task, :requestor => person, :target => person)
  58 + t4 = create(Task, :requestor => person, :target => person, :status => Task::Status::FINISHED)
  59 +
  60 + get "/api/v1/tasks/#{t4.id}?#{params.to_query}"
  61 + json = JSON.parse(last_response.body)
  62 + assert_equal t4.id, json["task"]["id"]
  63 + end
41 64
42 - should 'return task by community' do 65 + should 'find the current user task even it is for community' do
43 community = fast_create(Community) 66 community = fast_create(Community)
44 community.add_admin(person) 67 community.add_admin(person)
  68 + t2 = create(Task, :requestor => person, :target => community)
45 69
46 - task = create(Task, :requestor => person, :target => community)  
47 - assert person.is_member_of?(community) 70 + t3 = create(Task, :requestor => person, :target => person)
48 71
49 - get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}" 72 + get "/api/v1/tasks/#{t2.id}?#{params.to_query}"
50 json = JSON.parse(last_response.body) 73 json = JSON.parse(last_response.body)
51 - assert_equal task.id, json["task"]["id"] 74 + assert_equal t2.id, json["task"]["id"]
52 end 75 end
53 76
54 - should 'not return task by community if user has no permission to view it' do  
55 - community = fast_create(Community)  
56 - task = create(Task, :requestor => person, :target => community)  
57 - assert !person.is_member_of?(community) 77 + should 'find the current user task even it is for environment' do
  78 + environment.add_admin(person)
  79 + t1 = create(Task, :requestor => person, :target => environment)
58 80
59 - get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}"  
60 - assert_equal 403, last_response.status  
61 - end 81 + t3 = create(Task, :requestor => person, :target => person)
62 82
63 - should 'create task in a community' do  
64 - community = fast_create(Community)  
65 - give_permission(person, 'perform_task', community)  
66 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}" 83 + get "/api/v1/tasks/#{t1.id}?#{params.to_query}"
67 json = JSON.parse(last_response.body) 84 json = JSON.parse(last_response.body)
68 - assert_not_nil json["task"]["id"] 85 + assert_equal t1.id, json["task"]["id"]
69 end 86 end
70 87
71 - should 'create task defining the requestor as current profile logged in' do 88 +
  89 + should 'list all tasks of user' do
  90 + environment.add_admin(person)
  91 + t1 = create(Task, :requestor => person, :target => environment)
  92 +
72 community = fast_create(Community) 93 community = fast_create(Community)
73 - community.add_member(person) 94 + community.add_admin(person)
  95 + t2 = create(Task, :requestor => person, :target => community)
74 96
75 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}"  
76 - json = JSON.parse(last_response.body) 97 + t3 = create(Task, :requestor => person, :target => person)
  98 + t4 = create(Task, :requestor => person, :target => person, :status => Task::Status::FINISHED)
77 99
78 - assert_equal person, Task.last.requestor 100 + get "/api/v1/tasks?#{params.to_query}"
  101 + json = JSON.parse(last_response.body)
  102 + assert_equivalent [t1.id, t2.id, t3.id, t4.id], json["tasks"].map { |a| a["id"] }
79 end 103 end
80 104
81 - should 'create task defining the target as the community' do 105 + should 'list all pending tasks of user' do
  106 + environment.add_admin(person)
  107 + t1 = create(Task, :requestor => person, :target => environment, :status => Task::Status::ACTIVE)
  108 +
82 community = fast_create(Community) 109 community = fast_create(Community)
83 - community.add_member(person) 110 + community.add_admin(person)
  111 + t2 = create(Task, :requestor => person, :target => community, :status => Task::Status::ACTIVE)
84 112
85 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}"  
86 - json = JSON.parse(last_response.body) 113 + t3 = create(Task, :requestor => person, :target => person, :status => Task::Status::ACTIVE)
  114 + t4 = create(Task, :requestor => person, :target => person, :status => Task::Status::FINISHED)
87 115
88 - assert_equal community, Task.last.target 116 + get "/api/v1/tasks?#{params.merge(:status => Task::Status::ACTIVE).to_query}"
  117 + json = JSON.parse(last_response.body)
  118 + assert_equivalent [t1.id, t2.id, t3.id], json["tasks"].map { |a| a["id"] }
89 end 119 end
90 120
91 - #############################  
92 - # Person Tasks #  
93 - #############################  
94 121
95 - should 'return task by person' do  
96 - task = create(Task, :requestor => person, :target => person)  
97 - get "/api/v1/people/#{person.id}/tasks/#{task.id}?#{params.to_query}"  
98 - json = JSON.parse(last_response.body)  
99 - assert_equal task.id, json["task"]["id"]  
100 - end 122 + should 'list tasks with pagination' do
  123 + Task.destroy_all
  124 + t1 = create(Task, :requestor => person, :target => person)
  125 + t2 = create(Task, :requestor => person, :target => person)
101 126
102 - should 'not return task by person if user has no permission to view it' do  
103 - some_person = fast_create(Person)  
104 - task = create(Task, :requestor => person, :target => some_person) 127 + params[:page] = 1
  128 + params[:per_page] = 1
  129 + get "/api/v1/tasks/?#{params.to_query}"
  130 + json_page_one = JSON.parse(last_response.body)
105 131
106 - get "/api/v1/people/#{some_person.id}/tasks/#{task.id}?#{params.to_query}"  
107 - assert_equal 403, last_response.status  
108 - end 132 + params[:page] = 2
  133 + params[:per_page] = 1
  134 + get "/api/v1/tasks/?#{params.to_query}"
  135 + json_page_two = JSON.parse(last_response.body)
109 136
110 - should 'create task for person' do  
111 - post "/api/v1/people/#{person.id}/tasks?#{params.to_query}"  
112 - json = JSON.parse(last_response.body)  
113 - assert_not_nil json["task"]["id"] 137 + assert_includes json_page_one["tasks"].map { |a| a["id"] }, t2.id
  138 + assert_not_includes json_page_one["tasks"].map { |a| a["id"] }, t1.id
  139 +
  140 + assert_includes json_page_two["tasks"].map { |a| a["id"] }, t1.id
  141 + assert_not_includes json_page_two["tasks"].map { |a| a["id"] }, t2.id
114 end 142 end
115 143
116 - should 'create task for another person' do  
117 - some_person = fast_create(Person)  
118 - post "/api/v1/people/#{some_person.id}/tasks?#{params.to_query}" 144 + should 'list tasks with timestamp' do
  145 + t1 = create(Task, :requestor => person, :target => person)
  146 + t2 = create(Task, :requestor => person, :target => person, :created_at => Time.zone.now)
  147 +
  148 + t1.created_at = Time.zone.now + 3.hours
  149 + t1.save!
  150 +
  151 +
  152 + params[:timestamp] = Time.zone.now + 1.hours
  153 + get "/api/v1/tasks/?#{params.to_query}"
119 json = JSON.parse(last_response.body) 154 json = JSON.parse(last_response.body)
120 155
121 - assert_equal some_person, Task.last.target 156 + assert_includes json["tasks"].map { |a| a["id"] }, t1.id
  157 + assert_not_includes json["tasks"].map { |a| a["id"] }, t2.id
122 end 158 end
123 159
124 - should 'create task defining the target as a person' do  
125 - post "/api/v1/people/#{person.id}/tasks?#{params.to_query}"  
126 - json = JSON.parse(last_response.body) 160 + task_actions=%w[finish cancel]
  161 + task_actions_state={"finish"=>"FINISHED","cancel"=>"CANCELLED"}
  162 + task_actions.each do |action|
  163 + should "person be able to #{action} his own task" do
  164 + person1 = fast_create(Person)
  165 + task = create(Task, :requestor => person1, :target => person)
  166 + put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
  167 + assert_equal person.reload.id, task.reload.closed_by_id
  168 + assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status
  169 + end
  170 +
  171 + should "person be able to #{action} environment task if it's admin user" do
  172 + environment = Environment.default
  173 + environment.add_admin(person)
  174 + task = create(Task, :requestor => person, :target => environment)
  175 + put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
  176 + assert_equal person.reload.id, task.reload.closed_by_id
  177 + assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status
  178 + end
  179 +
  180 + should "person be able to #{action} community task if it has permission on it" do
  181 + community = fast_create(Community)
  182 + community.add_member(person)
  183 + give_permission(person, 'perform_task', community)
  184 + task = create(Task, :requestor => person, :target => community)
  185 + put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
  186 + assert_equal person.reload.id, task.reload.closed_by_id
  187 + assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status
  188 + end
  189 +
  190 + should "person not be able to #{action} community task if it has no permission on it" do
  191 + community = fast_create(Community)
  192 + community.add_member(person)
  193 + task = create(Task, :requestor => person, :target => community)
  194 + put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
  195 + assert_equal person.reload.id, task.reload.closed_by_id
  196 + assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status
  197 + end
  198 +
  199 + should "person not be able to #{action} other person's task" do
  200 + user = fast_create(User)
  201 + person1 = fast_create(Person, :user_id => user)
  202 + task = create(Task, :requestor => person, :target => person1)
  203 + put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
  204 + assert_nil task.reload.closed_by_id
  205 + assert_equal Task::Status::ACTIVE, task.status
  206 + end
  207 + end
127 208
128 - assert_equal person, Task.last.target 209 + #################################################
  210 + # Person, Community and Enterprise Tasks #
  211 + #################################################
  212 +
  213 + [Person, Community, Enterprise].map do |profile_class|
  214 + define_method "test_should_return_task_by_#{profile_class.name.underscore}" do
  215 + target = profile_class == Person ? person : fast_create(profile_class)
  216 + target.add_admin(person) if target.respond_to?('add_admin')
  217 +
  218 + task = create(Task, :requestor => person, :target => target)
  219 + get "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks/#{task.id}?#{params.to_query}"
  220 + json = JSON.parse(last_response.body)
  221 + assert_equal task.id, json["task"]["id"]
  222 + end
  223 +
  224 + define_method "test_should_not_return_task_ by#{profile_class.name.underscore}_for_unlogged_users" do
  225 + logout_api
  226 + target = profile_class == Person ? person : fast_create(profile_class)
  227 + target.add_admin(person) if target.respond_to?('add_admin')
  228 +
  229 + task = create(Task, :requestor => person, :target => target)
  230 + get "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks/#{task.id}?#{params.to_query}"
  231 + json = JSON.parse(last_response.body)
  232 + assert_equal 401, last_response.status
  233 + end
  234 +
  235 + define_method "test_should_not_return_task_by_#{profile_class.name.underscore}_if_user_has_no_permission_to_view_it" do
  236 + target = fast_create(profile_class)
  237 + task = create(Task, :requestor => person, :target => target)
  238 +
  239 + get "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks/#{task.id}?#{params.to_query}"
  240 + assert_equal 403, last_response.status
  241 + end
  242 +
  243 + define_method "test_should_create_task_for_#{profile_class.name.underscore}" do
  244 + target = profile_class == Person ? person : fast_create(profile_class)
  245 + Person.any_instance.expects(:has_permission?).with(:perform_task, target).returns(true)
  246 +
  247 + post "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks?#{params.to_query}"
  248 + json = JSON.parse(last_response.body)
  249 + assert_not_nil json["task"]["id"]
  250 + end
  251 +
  252 + define_method "test_should_not_create_task_for_#{profile_class.name.underscore}_person_has_no_permission" do
  253 + target = fast_create(profile_class)
  254 +
  255 + post "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks?#{params.to_query}"
  256 + json = JSON.parse(last_response.body)
  257 + assert_equal 403, last_response.status
  258 + end
  259 +
  260 + define_method "test_should_not_create_task_in_#{profile_class.name.underscore}_for_unlogged_users" do
  261 + logout_api
  262 + target = profile_class == Person ? person : fast_create(profile_class)
  263 + Person.any_instance.stubs(:has_permission?).with(:perform_task, target).returns(true)
  264 +
  265 + post "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks?#{params.to_query}"
  266 +
  267 + json = JSON.parse(last_response.body)
  268 + assert_equal 401, last_response.status
  269 + end
  270 +
  271 + define_method "test_should_create_task_defining_the_target_as_a_#{profile_class.name.underscore}" do
  272 + target = profile_class == Person ? person : fast_create(profile_class)
  273 + Person.any_instance.stubs(:has_permission?).with(:perform_task, target).returns(true)
  274 +
  275 + post "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks?#{params.to_query}"
  276 + json = JSON.parse(last_response.body)
  277 +
  278 + assert_equal target, Task.last.target
  279 + end
  280 +
  281 + define_method "test_should_create_task_on_#{profile_class.name.underscore}_defining_the_requestor_as_current_profile_logged_in" do
  282 + target = profile_class == Person ? person : fast_create(profile_class)
  283 + Person.any_instance.stubs(:has_permission?).with(:perform_task, target).returns(true)
  284 +
  285 + post "/api/v1/#{profile_class.name.underscore.pluralize}/#{target.id}/tasks?#{params.to_query}"
  286 + json = JSON.parse(last_response.body)
  287 +
  288 + assert_equal person, Task.last.requestor
  289 + end
129 end 290 end
130 291
131 - #############################  
132 - # Enterprise Tasks #  
133 - ############################# 292 + should 'list all tasks of user in people context' do
  293 + environment.add_admin(person)
  294 + t1 = create(Task, :requestor => person, :target => environment)
134 295
135 - should 'return task by enterprise' do  
136 - enterprise = fast_create(Enterprise)  
137 - enterprise.add_admin(person) 296 + community = fast_create(Community)
  297 + community.add_admin(person)
  298 + t2 = create(Task, :requestor => person, :target => community)
138 299
139 - task = create(Task, :requestor => person, :target => enterprise)  
140 - assert person.is_member_of?(enterprise) 300 + t3 = create(Task, :requestor => person, :target => person)
141 301
142 - get "/api/v1/enterprises/#{enterprise.id}/tasks/#{task.id}?#{params.to_query}" 302 + get "/api/v1/people/#{person.id}/tasks?#{params.to_query}"
143 json = JSON.parse(last_response.body) 303 json = JSON.parse(last_response.body)
144 - assert_equal task.id, json["task"]["id"] 304 + assert_equivalent [t1.id, t2.id, t3.id], json["tasks"].map { |a| a["id"] }
145 end 305 end
146 306
147 - should 'not return task by enterprise if user has no permission to view it' do  
148 - enterprise = fast_create(Enterprise)  
149 - task = create(Task, :requestor => person, :target => enterprise)  
150 - assert !person.is_member_of?(enterprise)  
151 -  
152 - get "/api/v1/enterprises/#{enterprise.id}/tasks/#{task.id}?#{params.to_query}"  
153 - assert_equal 403, last_response.status  
154 - end 307 + should 'list all pending tasks of user in people context' do
  308 + environment.add_admin(person)
  309 + t1 = create(Task, :requestor => person, :target => environment)
  310 + t2 = create(Task, :requestor => person, :target => environment, :status => Task::Status::FINISHED )
155 311
156 - should 'create task in a enterprise' do  
157 - enterprise = fast_create(Enterprise)  
158 - give_permission(person, 'perform_task', enterprise)  
159 - post "/api/v1/enterprises/#{enterprise.id}/tasks?#{params.to_query}"  
160 - json = JSON.parse(last_response.body)  
161 - assert_not_nil json["task"]["id"]  
162 - end 312 + community = fast_create(Community)
  313 + community.add_admin(person)
  314 + t3 = create(Task, :requestor => person, :target => community)
  315 + t4 = create(Task, :requestor => person, :target => community, :status => Task::Status::FINISHED)
163 316
164 - should 'create task defining the target as the enterprise' do  
165 - enterprise = fast_create(Enterprise)  
166 - enterprise.add_member(person) 317 + t5 = create(Task, :requestor => person, :target => person)
  318 + t6 = create(Task, :requestor => person, :target => person, :status => Task::Status::FINISHED)
167 319
168 - post "/api/v1/enterprises/#{enterprise.id}/tasks?#{params.to_query}" 320 + get "/api/v1/people/#{person.id}/tasks?#{params.merge(:status => Task::Status::ACTIVE).to_query}"
169 json = JSON.parse(last_response.body) 321 json = JSON.parse(last_response.body)
170 -  
171 - assert_equal enterprise, Task.last.target 322 + assert_equivalent [t1.id, t3.id, t5.id], json["tasks"].map { |a| a["id"] }
172 end 323 end
  324 +
173 end 325 end
test/unit/person_test.rb
@@ -2005,4 +2005,5 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -2005,4 +2005,5 @@ class PersonTest &lt; ActiveSupport::TestCase
2005 person.remove_profile_from_circle(community, circle) 2005 person.remove_profile_from_circle(community, circle)
2006 assert_equivalent [circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) 2006 assert_equivalent [circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle)
2007 end 2007 end
  2008 +
2008 end 2009 end
test/unit/task_test.rb
@@ -324,24 +324,6 @@ class TaskTest &lt; ActiveSupport::TestCase @@ -324,24 +324,6 @@ class TaskTest &lt; ActiveSupport::TestCase
324 task.activate 324 task.activate
325 end 325 end
326 326
327 - should 'filter tasks to a profile' do  
328 - requestor = fast_create(Person)  
329 - person = fast_create(Person)  
330 - another_person = fast_create(Person)  
331 - environment = Environment.default  
332 - environment.add_admin(person)  
333 - t1 = create(Task, :requestor => requestor, :target => person)  
334 - t2 = create(Task, :requestor => requestor, :target => person)  
335 - t3 = create(Task, :requestor => requestor, :target => environment)  
336 - t4 = create(Task, :requestor => requestor, :target => another_person)  
337 -  
338 - assert_includes Task.to(person), t1  
339 - assert_includes Task.to(person), t2  
340 - assert_includes Task.to(person), t3  
341 - assert_not_includes Task.to(person), t4  
342 - assert_includes Task.to(another_person), t4  
343 - end  
344 -  
345 should 'filter tasks by type with scope' do 327 should 'filter tasks by type with scope' do
346 class CleanHouse < Task; end 328 class CleanHouse < Task; end
347 class FeedDog < Task; end 329 class FeedDog < Task; end
@@ -508,6 +490,87 @@ class TaskTest &lt; ActiveSupport::TestCase @@ -508,6 +490,87 @@ class TaskTest &lt; ActiveSupport::TestCase
508 assert_equal person, t.reload.closed_by 490 assert_equal person, t.reload.closed_by
509 end 491 end
510 492
  493 + should 'named scope to get tasks of a profile' do
  494 + requestor = fast_create(Person)
  495 + person = fast_create(Person)
  496 + another_person = fast_create(Person)
  497 + t1 = create(Task, :requestor => requestor, :target => person)
  498 + t2 = create(Task, :requestor => requestor, :target => another_person)
  499 + t3 = create(Task, :requestor => requestor, :target => person)
  500 +
  501 + assert_equivalent [t1,t3], Task.to(person)
  502 + end
  503 +
  504 + should 'named scope to get environment tasks if passed profile is environment admin' do
  505 + requestor = fast_create(Person)
  506 + person = fast_create(Person)
  507 + another_person = fast_create(Person)
  508 + environment = Environment.default
  509 + environment.add_admin(person)
  510 + t1 = create(Task, :requestor => requestor, :target => person)
  511 + t2 = create(Task, :requestor => requestor, :target => another_person)
  512 + t3 = create(Task, :requestor => requestor, :target => environment)
  513 +
  514 + assert_equivalent [t1,t3], Task.to(person)
  515 + end
  516 +
  517 + should 'named scope to not get environment tasks if passed profile is not environment admin' do
  518 + requestor = fast_create(Person)
  519 + person = fast_create(Person)
  520 + another_person = fast_create(Person)
  521 + environment = Environment.default
  522 + t1 = create(Task, :requestor => requestor, :target => person)
  523 + t2 = create(Task, :requestor => requestor, :target => another_person)
  524 + t3 = create(Task, :requestor => requestor, :target => environment)
  525 +
  526 + assert_equivalent [t1], Task.to(person)
  527 + end
  528 +
  529 + should 'named scope to get communities tasks if passed profile has perform_task permission' do
  530 + requestor = fast_create(Person)
  531 + person = fast_create(Person)
  532 + another_person = fast_create(Person)
  533 + community = fast_create(Community)
  534 + community.add_member(person)
  535 + person.expects(:has_permission?).with(:perform_task, community).returns(true)
  536 + t1 = create(Task, :requestor => requestor, :target => person)
  537 + t2 = create(Task, :requestor => requestor, :target => another_person)
  538 + t3 = create(Task, :requestor => requestor, :target => community)
  539 +
  540 + assert_equivalent [t1, t3], Task.to(person)
  541 + end
  542 +
  543 +
  544 + should 'named scope to not get communities tasks if passed profile has no perform_task permission in community' do
  545 + requestor = fast_create(Person)
  546 + person = fast_create(Person)
  547 + another_person = fast_create(Person)
  548 + community = fast_create(Community)
  549 + community.add_member(person)
  550 + person.expects(:has_permission?).with(:perform_task, community).returns(false)
  551 + t1 = create(Task, :requestor => requestor, :target => person)
  552 + t2 = create(Task, :requestor => requestor, :target => another_person)
  553 + t3 = create(Task, :requestor => requestor, :target => community)
  554 +
  555 + assert_equivalent [t1], Task.to(person)
  556 + end
  557 +
  558 + should 'named scope to return environment, person and communities tasks if user has permission' do
  559 + requestor = fast_create(Person)
  560 + person = fast_create(Person)
  561 + another_person = fast_create(Person)
  562 + community = fast_create(Community)
  563 + community.add_member(person)
  564 + person.expects(:has_permission?).with(:perform_task, community).returns(true)
  565 + environment = Environment.default
  566 + environment.add_admin(person)
  567 + t1 = create(Task, :requestor => requestor, :target => person)
  568 + t2 = create(Task, :requestor => requestor, :target => another_person)
  569 + t3 = create(Task, :requestor => requestor, :target => community)
  570 + t4 = create(Task, :requestor => requestor, :target => environment)
  571 + assert_equivalent [t1,t3,t4], Task.to(person)
  572 + end
  573 +
511 protected 574 protected
512 575
513 def sample_user 576 def sample_user