Commit 4bfa4aaae5e636c392779411c3c640c008e59f0d

Authored by Victor Costa
2 parents 98f67e15 742a886d
Exists in fix_sign_up_form

Merge branch 'all_pending_tasks_api' into 'master'

api: list all pending tasks for the current person



See merge request !979
app/api/entities.rb
@@ -263,6 +263,14 @@ module Api @@ -263,6 +263,14 @@ module Api
263 root 'tasks', 'task' 263 root 'tasks', 'task'
264 expose :id 264 expose :id
265 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
266 end 274 end
267 275
268 class Environment < Entity 276 class Environment < Entity
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
@@ -124,8 +124,8 @@ module Api @@ -124,8 +124,8 @@ module Api
124 present_partial article, with: Entities::Article, params: params, current_person: current_person 124 present_partial article, with: Entities::Article, params: params, current_person: current_person
125 end 125 end
126 126
127 - def present_articles_for_asset(asset, method = 'articles')  
128 - articles = find_articles(asset, method) 127 + def present_articles_for_asset(asset, method_or_relation = 'articles')
  128 + articles = find_articles(asset, method_or_relation)
129 present_articles(articles) 129 present_articles(articles)
130 end 130 end
131 131
@@ -133,8 +133,8 @@ module Api @@ -133,8 +133,8 @@ module Api
133 present_partial paginate(articles), :with => Entities::Article, :params => params, current_person: current_person 133 present_partial paginate(articles), :with => Entities::Article, :params => params, current_person: current_person
134 end 134 end
135 135
136 - def find_articles(asset, method = 'articles')  
137 - articles = select_filtered_collection_of(asset, method, params) 136 + def find_articles(asset, method_or_relation = 'articles')
  137 + articles = select_filtered_collection_of(asset, method_or_relation, params)
138 if current_person.present? 138 if current_person.present?
139 articles = articles.display_filter(current_person, nil) 139 articles = articles.display_filter(current_person, nil)
140 else 140 else
@@ -143,8 +143,9 @@ module Api @@ -143,8 +143,9 @@ module Api
143 articles 143 articles
144 end 144 end
145 145
146 - def find_task(asset, id)  
147 - task = asset.tasks.find_by(id: id) 146 + def find_task(asset, method_or_relation, id)
  147 + task = is_a_relation?(method_or_relation) ? method_or_relation : asset.send(method_or_relation)
  148 + task = task.find_by_id(id)
148 not_found! if task.blank? 149 not_found! if task.blank?
149 current_person.has_permission?(task.permission, asset) ? task : forbidden! 150 current_person.has_permission?(task.permission, asset) ? task : forbidden!
150 end 151 end
@@ -152,6 +153,7 @@ module Api @@ -152,6 +153,7 @@ module Api
152 def post_task(asset, params) 153 def post_task(asset, params)
153 klass_type= params[:content_type].nil? ? 'Task' : params[:content_type] 154 klass_type= params[:content_type].nil? ? 'Task' : params[:content_type]
154 return forbidden! unless klass_type.constantize <= Task 155 return forbidden! unless klass_type.constantize <= Task
  156 + return forbidden! if !current_person.has_permission?(:perform_task, asset)
155 157
156 task = klass_type.constantize.new(params[:task]) 158 task = klass_type.constantize.new(params[:task])
157 task.requestor_id = current_person.id 159 task.requestor_id = current_person.id
@@ -164,15 +166,24 @@ module Api @@ -164,15 +166,24 @@ module Api
164 present_partial task, :with => Entities::Task 166 present_partial task, :with => Entities::Task
165 end 167 end
166 168
167 - def present_task(asset)  
168 - task = find_task(asset, params[:id]) 169 + def find_tasks(asset, method_or_relation = 'tasks')
  170 + return forbidden! if !current_person.has_permission?(:perform_task, asset)
  171 + tasks = select_filtered_collection_of(asset, method_or_relation, params)
  172 + tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}
  173 + tasks
  174 + end
  175 +
  176 + def present_task(asset, method_or_relation = 'tasks')
  177 + task = find_task(asset, method_or_relation, params[:id])
169 present_partial task, :with => Entities::Task 178 present_partial task, :with => Entities::Task
170 end 179 end
171 180
172 - def present_tasks(asset)  
173 - tasks = select_filtered_collection_of(asset, 'tasks', params)  
174 - tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}  
175 - return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) 181 + def present_tasks_for_asset(asset, method_or_relation = 'tasks')
  182 + tasks = find_tasks(asset, method_or_relation)
  183 + present_tasks(tasks)
  184 + end
  185 +
  186 + def present_tasks(tasks)
176 present_partial tasks, :with => Entities::Task 187 present_partial tasks, :with => Entities::Task
177 end 188 end
178 189
@@ -181,7 +192,6 @@ module Api @@ -181,7 +192,6 @@ module Api
181 conditions = {} 192 conditions = {}
182 from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from] 193 from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from]
183 until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until] 194 until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until]
184 -  
185 conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil? 195 conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil?
186 196
187 conditions[:created_at] = period(from_date, until_date) if from_date || until_date 197 conditions[:created_at] = period(from_date, until_date) if from_date || until_date
@@ -191,7 +201,7 @@ module Api @@ -191,7 +201,7 @@ module Api
191 end 201 end
192 202
193 # changing make_order_with_parameters to avoid sql injection 203 # changing make_order_with_parameters to avoid sql injection
194 - def make_order_with_parameters(object, method, params) 204 + def make_order_with_parameters(object, method_or_relation, params)
195 order = "created_at DESC" 205 order = "created_at DESC"
196 unless params[:order].blank? 206 unless params[:order].blank?
197 if params[:order].include? '\'' or params[:order].include? '"' 207 if params[:order].include? '\'' or params[:order].include? '"'
@@ -200,9 +210,9 @@ module Api @@ -200,9 +210,9 @@ module Api
200 order = 'RANDOM()' 210 order = 'RANDOM()'
201 else 211 else
202 field_name, direction = params[:order].split(' ') 212 field_name, direction = params[:order].split(' ')
203 - assoc = object.class.reflect_on_association(method.to_sym)  
204 - if !field_name.blank? and assoc  
205 - if assoc.klass.attribute_names.include? field_name 213 + assoc_class = extract_associated_classname(method_or_relation)
  214 + if !field_name.blank? and assoc_class
  215 + if assoc_class.attribute_names.include? field_name
206 if direction.present? and ['ASC','DESC'].include? direction.upcase 216 if direction.present? and ['ASC','DESC'].include? direction.upcase
207 order = "#{field_name} #{direction.upcase}" 217 order = "#{field_name} #{direction.upcase}"
208 end 218 end
@@ -213,12 +223,14 @@ module Api @@ -213,12 +223,14 @@ module Api
213 return order 223 return order
214 end 224 end
215 225
216 - def make_timestamp_with_parameters_and_method(params, method) 226 + def make_timestamp_with_parameters_and_method(params, method_or_relation)
217 timestamp = nil 227 timestamp = nil
218 if params[:timestamp] 228 if params[:timestamp]
219 datetime = DateTime.parse(params[:timestamp]) 229 datetime = DateTime.parse(params[:timestamp])
220 - table_name = method.to_s.singularize.camelize.constantize.table_name  
221 - timestamp = "#{table_name}.updated_at >= '#{datetime}'" 230 + table_name = extract_associated_tablename(method_or_relation)
  231 + assoc_class = extract_associated_classname(method_or_relation)
  232 + date_atrr = assoc_class.attribute_names.include?('updated_at') ? 'updated_at' : 'created_at'
  233 + timestamp = "#{table_name}.#{date_atrr} >= '#{datetime}'"
222 end 234 end
223 235
224 timestamp 236 timestamp
@@ -243,12 +255,12 @@ module Api @@ -243,12 +255,12 @@ module Api
243 end 255 end
244 end 256 end
245 257
246 - def select_filtered_collection_of(object, method, params) 258 + def select_filtered_collection_of(object, method_or_relation, params)
247 conditions = make_conditions_with_parameter(params) 259 conditions = make_conditions_with_parameter(params)
248 - order = make_order_with_parameters(object,method,params)  
249 - timestamp = make_timestamp_with_parameters_and_method(params, method) 260 + order = make_order_with_parameters(object,method_or_relation,params)
  261 + timestamp = make_timestamp_with_parameters_and_method(params, method_or_relation)
250 262
251 - objects = object.send(method) 263 + objects = is_a_relation?(method_or_relation) ? method_or_relation : object.send(method_or_relation)
252 objects = by_reference(objects, params) 264 objects = by_reference(objects, params)
253 objects = by_categories(objects, params) 265 objects = by_categories(objects, params)
254 266
@@ -394,10 +406,27 @@ module Api @@ -394,10 +406,27 @@ module Api
394 end 406 end
395 private 407 private
396 408
  409 + def extract_associated_tablename(method_or_relation)
  410 + extract_associated_classname(method_or_relation).table_name
  411 + end
  412 +
  413 + def extract_associated_classname(method_or_relation)
  414 + if is_a_relation?(method_or_relation)
  415 + method_or_relation.blank? ? '' : method_or_relation.first.class
  416 + else
  417 + method_or_relation.to_s.singularize.camelize.constantize
  418 + end
  419 + end
  420 +
  421 + def is_a_relation?(method_or_relation)
  422 + method_or_relation.kind_of?(ActiveRecord::Relation)
  423 + end
  424 +
  425 +
397 def parser_params(params) 426 def parser_params(params)
398 parsed_params = {} 427 parsed_params = {}
399 params.map do |k,v| 428 params.map do |k,v|
400 - parsed_params[k.to_sym] = v if DEFAULT_ALLOWED_PARAMETERS.include?(k.to_sym) 429 + parsed_params[k.to_sym] = v if ALLOWED_PARAMETERS.include?(k.to_sym)
401 end 430 end
402 parsed_params 431 parsed_params
403 end 432 end
app/api/v1/tasks.rb
@@ -3,9 +3,12 @@ module Api @@ -3,9 +3,12 @@ module Api
3 class Tasks < Grape::API 3 class Tasks < Grape::API
4 before { authenticate! } 4 before { authenticate! }
5 5
  6 + MAX_PER_PAGE = 50
  7 +
6 resource :tasks do 8 resource :tasks do
7 9
8 - # Collect tasks 10 + paginate max_per_page: MAX_PER_PAGE
  11 + # Collect all tasks that current person has permission
9 # 12 #
10 # Parameters: 13 # Parameters:
11 # 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
@@ -15,20 +18,19 @@ module Api @@ -15,20 +18,19 @@ module Api
15 # Example Request: 18 # Example Request:
16 # 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
17 get do 20 get do
18 - present_tasks(environment) 21 + tasks = Task.to(current_person)
  22 + present_tasks_for_asset(current_person, tasks)
19 end 23 end
20 24
21 desc "Return the task id" 25 desc "Return the task id"
22 get ':id' do 26 get ':id' do
23 - task = find_task(environment, params[:id])  
24 - present_partial task, :with => Entities::Task 27 + present_task(current_person, Task.to(current_person))
25 end 28 end
26 29
27 %w[finish cancel].each do |action| 30 %w[finish cancel].each do |action|
28 desc "#{action.capitalize} a task" 31 desc "#{action.capitalize} a task"
29 put ":id/#{action}" do 32 put ":id/#{action}" do
30 - authenticate!  
31 - task = find_task(current_person, params[:id]) 33 + task = find_task(current_person, Task.to(current_person), params[:id])
32 task.send(action, current_person) if (task.status == Task::Status::ACTIVE) 34 task.send(action, current_person) if (task.status == Task::Status::ACTIVE)
33 present_partial task, :with => Entities::Task 35 present_partial task, :with => Entities::Task
34 end 36 end
@@ -42,7 +44,8 @@ module Api @@ -42,7 +44,8 @@ module Api
42 resource :tasks do 44 resource :tasks do
43 get do 45 get do
44 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 46 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
45 - present_tasks(profile) 47 + tasks = Task.to(profile)
  48 + present_tasks_for_asset(profile, tasks)
46 end 49 end
47 50
48 get ':id' do 51 get ':id' do
app/controllers/my_profile/tasks_controller.rb
@@ -14,7 +14,7 @@ class TasksController &lt; MyProfileController @@ -14,7 +14,7 @@ class TasksController &lt; MyProfileController
14 @filter_text = params[:filter_text].presence 14 @filter_text = params[:filter_text].presence
15 @filter_responsible = params[:filter_responsible] 15 @filter_responsible = params[:filter_responsible]
16 @task_types = Task.pending_types_for(profile) 16 @task_types = Task.pending_types_for(profile)
17 - @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) 17 + @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])
18 @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? 18 @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present?
19 @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) 19 @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
20 @failed = params ? params[:failed] : {} 20 @failed = params ? params[:failed] : {}
@@ -101,7 +101,7 @@ class TasksController &lt; MyProfileController @@ -101,7 +101,7 @@ class TasksController &lt; MyProfileController
101 def search_tasks 101 def search_tasks
102 filter_type = params[:filter_type].presence 102 filter_type = params[:filter_type].presence
103 filter_text = params[:filter_text].presence 103 filter_text = params[:filter_text].presence
104 - result = Task.pending_all(profile,filter_type, filter_text) 104 + result = Task.pending_all_by_filter(profile,filter_type, filter_text)
105 105
106 render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} } 106 render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} }
107 end 107 end
app/models/task.rb
@@ -314,7 +314,7 @@ class Task &lt; ApplicationRecord @@ -314,7 +314,7 @@ class Task &lt; ApplicationRecord
314 where "LOWER(#{field}) LIKE ?", "%#{value.downcase}%" 314 where "LOWER(#{field}) LIKE ?", "%#{value.downcase}%"
315 end 315 end
316 } 316 }
317 - scope :pending_all, -> profile, filter_type, filter_text { 317 + scope :pending_all_by_filter, -> profile, filter_type, filter_text {
318 self.to(profile).without_spam.pending.of(filter_type).like('data', filter_text) 318 self.to(profile).without_spam.pending.of(filter_type).like('data', filter_text)
319 } 319 }
320 320
@@ -323,10 +323,17 @@ class Task &lt; ApplicationRecord @@ -323,10 +323,17 @@ class Task &lt; ApplicationRecord
323 if profile.person? 323 if profile.person?
324 envs_ids = Environment.all.select{ |env| profile.is_admin?(env) }.map{ |env| "target_id = #{env.id}"}.join(' OR ') 324 envs_ids = Environment.all.select{ |env| profile.is_admin?(env) }.map{ |env| "target_id = #{env.id}"}.join(' OR ')
325 environment_condition = envs_ids.blank? ? nil : "(target_type = 'Environment' AND (#{envs_ids}))" 325 environment_condition = envs_ids.blank? ? nil : "(target_type = 'Environment' AND (#{envs_ids}))"
  326 +
  327 + organizations = profile.memberships.all.select do |organization|
  328 + profile.has_permission?(:perform_task, organization)
  329 + end
  330 + organization_ids = organizations.map{ |organization| "target_id = #{organization.id}"}.join(' OR ')
  331 +
  332 + organization_conditions = organization_ids.blank? ? nil : "(target_type = 'Profile' AND (#{organization_ids}))"
326 end 333 end
327 profile_condition = "(target_type = 'Profile' AND target_id = #{profile.id})" 334 profile_condition = "(target_type = 'Profile' AND target_id = #{profile.id})"
328 335
329 - where [environment_condition, profile_condition].compact.join(' OR ') 336 + where [environment_condition, organization_conditions, profile_condition].compact.join(' OR ')
330 } 337 }
331 338
332 scope :from_closed_date, -> closed_from { 339 scope :from_closed_date, -> closed_from {
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}"
@@ -50,144 +50,117 @@ class TasksTest &lt; ActiveSupport::TestCase @@ -50,144 +50,117 @@ class TasksTest &lt; ActiveSupport::TestCase
50 task = create(Task, :requestor => person, :target => environment) 50 task = create(Task, :requestor => person, :target => environment)
51 51
52 get "/api/v1/tasks/#{task.id}?#{params.to_query}" 52 get "/api/v1/tasks/#{task.id}?#{params.to_query}"
53 - assert_equal 403, last_response.status 53 + assert_equal 404, last_response.status
54 end 54 end
55 55
56 - #############################  
57 - # Community Tasks #  
58 - ############################# 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 59
60 - should 'return task by community' do  
61 - community = fast_create(Community)  
62 - community.add_admin(person)  
63 -  
64 - task = create(Task, :requestor => person, :target => community)  
65 - assert person.is_member_of?(community)  
66 -  
67 - get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}" 60 + get "/api/v1/tasks/#{t4.id}?#{params.to_query}"
68 json = JSON.parse(last_response.body) 61 json = JSON.parse(last_response.body)
69 - assert_equal task.id, json["task"]["id"] 62 + assert_equal t4.id, json["task"]["id"]
70 end 63 end
71 64
72 - should 'not return task by community for unlogged users' do  
73 - logout_api 65 + should 'find the current user task even it is for community' do
74 community = fast_create(Community) 66 community = fast_create(Community)
75 community.add_admin(person) 67 community.add_admin(person)
  68 + t2 = create(Task, :requestor => person, :target => community)
76 69
77 - task = create(Task, :requestor => person, :target => community)  
78 - assert person.is_member_of?(community) 70 + t3 = create(Task, :requestor => person, :target => person)
79 71
80 - get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}" 72 + get "/api/v1/tasks/#{t2.id}?#{params.to_query}"
81 json = JSON.parse(last_response.body) 73 json = JSON.parse(last_response.body)
82 - assert_equal 401, last_response.status 74 + assert_equal t2.id, json["task"]["id"]
83 end 75 end
84 76
85 - should 'not return task by community if user has no permission to view it' do  
86 - community = fast_create(Community)  
87 - task = create(Task, :requestor => person, :target => community)  
88 - 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)
89 80
90 - get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}"  
91 - assert_equal 403, last_response.status  
92 - end 81 + t3 = create(Task, :requestor => person, :target => person)
93 82
94 - should 'create task in a community' do  
95 - community = fast_create(Community)  
96 - give_permission(person, 'perform_task', community)  
97 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}" 83 + get "/api/v1/tasks/#{t1.id}?#{params.to_query}"
98 json = JSON.parse(last_response.body) 84 json = JSON.parse(last_response.body)
99 - assert_not_nil json["task"]["id"] 85 + assert_equal t1.id, json["task"]["id"]
100 end 86 end
101 87
102 - should 'not create task in a community for unlogged users' do  
103 - logout_api  
104 - community = fast_create(Community)  
105 - give_permission(person, 'perform_task', community)  
106 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}"  
107 - json = JSON.parse(last_response.body)  
108 - assert_equal 401, last_response.status  
109 - end  
110 88
111 - should 'create task defining the requestor as current profile logged in' do 89 + should 'list all tasks of user' do
  90 + environment.add_admin(person)
  91 + t1 = create(Task, :requestor => person, :target => environment)
  92 +
112 community = fast_create(Community) 93 community = fast_create(Community)
113 - community.add_member(person) 94 + community.add_admin(person)
  95 + t2 = create(Task, :requestor => person, :target => community)
114 96
115 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}"  
116 - 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)
117 99
118 - 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"] }
119 end 103 end
120 104
121 - 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 +
122 community = fast_create(Community) 109 community = fast_create(Community)
123 - community.add_member(person) 110 + community.add_admin(person)
  111 + t2 = create(Task, :requestor => person, :target => community, :status => Task::Status::ACTIVE)
124 112
125 - post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}"  
126 - 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)
127 115
128 - 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"] }
129 end 119 end
130 120
131 - #############################  
132 - # Person Tasks #  
133 - #############################  
134 121
135 - should 'return task by person' do  
136 - task = create(Task, :requestor => person, :target => person)  
137 - get "/api/v1/people/#{person.id}/tasks/#{task.id}?#{params.to_query}"  
138 - json = JSON.parse(last_response.body)  
139 - assert_equal task.id, json["task"]["id"]  
140 - 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)
141 126
142 - should 'not return task by person for unlogged users' do  
143 - logout_api  
144 - task = create(Task, :requestor => person, :target => person)  
145 - get "/api/v1/people/#{person.id}/tasks/#{task.id}?#{params.to_query}"  
146 - json = JSON.parse(last_response.body)  
147 - assert_equal 401, last_response.status  
148 - end 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)
149 131
150 - should 'not return task by person if user has no permission to view it' do  
151 - some_person = fast_create(Person)  
152 - task = create(Task, :requestor => person, :target => some_person) 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)
153 136
154 - get "/api/v1/people/#{some_person.id}/tasks/#{task.id}?#{params.to_query}"  
155 - assert_equal 403, last_response.status  
156 - end 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
157 139
158 - should 'create task for person' do  
159 - post "/api/v1/people/#{person.id}/tasks?#{params.to_query}"  
160 - json = JSON.parse(last_response.body)  
161 - assert_not_nil json["task"]["id"] 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
162 end 142 end
163 143
164 - should 'not create task in person for unlogged users' do  
165 - logout_api  
166 - post "/api/v1/people/#{person.id}/tasks?#{params.to_query}"  
167 - json = JSON.parse(last_response.body)  
168 - assert_equal 401, last_response.status  
169 - end 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)
170 147
171 - should 'create task for another person' do  
172 - some_person = fast_create(Person)  
173 - post "/api/v1/people/#{some_person.id}/tasks?#{params.to_query}"  
174 - json = JSON.parse(last_response.body) 148 + t1.created_at = Time.zone.now + 3.hours
  149 + t1.save!
175 150
176 - assert_equal some_person, Task.last.target  
177 - end  
178 151
179 - should 'create task defining the target as a person' do  
180 - post "/api/v1/people/#{person.id}/tasks?#{params.to_query}" 152 + params[:timestamp] = Time.zone.now + 1.hours
  153 + get "/api/v1/tasks/?#{params.to_query}"
181 json = JSON.parse(last_response.body) 154 json = JSON.parse(last_response.body)
182 155
183 - assert_equal 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
184 end 158 end
185 159
186 task_actions=%w[finish cancel] 160 task_actions=%w[finish cancel]
187 task_actions_state={"finish"=>"FINISHED","cancel"=>"CANCELLED"} 161 task_actions_state={"finish"=>"FINISHED","cancel"=>"CANCELLED"}
188 task_actions.each do |action| 162 task_actions.each do |action|
189 should "person be able to #{action} his own task" do 163 should "person be able to #{action} his own task" do
190 - login_api  
191 person1 = fast_create(Person) 164 person1 = fast_create(Person)
192 task = create(Task, :requestor => person1, :target => person) 165 task = create(Task, :requestor => person1, :target => person)
193 put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}" 166 put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
@@ -195,8 +168,35 @@ class TasksTest &lt; ActiveSupport::TestCase @@ -195,8 +168,35 @@ class TasksTest &lt; ActiveSupport::TestCase
195 assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status 168 assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status
196 end 169 end
197 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 +
198 should "person not be able to #{action} other person's task" do 199 should "person not be able to #{action} other person's task" do
199 - login_api  
200 user = fast_create(User) 200 user = fast_create(User)
201 person1 = fast_create(Person, :user_id => user) 201 person1 = fast_create(Person, :user_id => user)
202 task = create(Task, :requestor => person, :target => person1) 202 task = create(Task, :requestor => person, :target => person1)
@@ -206,69 +206,120 @@ class TasksTest &lt; ActiveSupport::TestCase @@ -206,69 +206,120 @@ class TasksTest &lt; ActiveSupport::TestCase
206 end 206 end
207 end 207 end
208 208
209 - #############################  
210 - # Enterprise Tasks #  
211 - ############################# 209 + #################################################
  210 + # Person, Community and Enterprise Tasks #
  211 + #################################################
212 212
213 - should 'return task by enterprise' do  
214 - enterprise = fast_create(Enterprise)  
215 - enterprise.add_admin(person) 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')
216 217
217 - task = create(Task, :requestor => person, :target => enterprise)  
218 - assert person.is_member_of?(enterprise) 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
219 223
220 - get "/api/v1/enterprises/#{enterprise.id}/tasks/#{task.id}?#{params.to_query}"  
221 - json = JSON.parse(last_response.body)  
222 - assert_equal task.id, json["task"]["id"]  
223 - end 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')
224 228
225 - should 'not return task by enterprise for unlogged users' do  
226 - logout_api  
227 - enterprise = fast_create(Enterprise)  
228 - enterprise.add_admin(person) 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
229 234
230 - task = create(Task, :requestor => person, :target => enterprise)  
231 - assert person.is_member_of?(enterprise) 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
232 242
233 - get "/api/v1/enterprises/#{enterprise.id}/tasks/#{task.id}?#{params.to_query}"  
234 - json = JSON.parse(last_response.body)  
235 - assert_equal 401, last_response.status  
236 - end 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)
237 246
238 - should 'not return task by enterprise if user has no permission to view it' do  
239 - enterprise = fast_create(Enterprise)  
240 - task = create(Task, :requestor => person, :target => enterprise)  
241 - assert !person.is_member_of?(enterprise) 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
242 251
243 - get "/api/v1/enterprises/#{enterprise.id}/tasks/#{task.id}?#{params.to_query}"  
244 - assert_equal 403, last_response.status  
245 - end 252 + define_method "test_should_not_create_task_for_#{profile_class.name.underscore}_person_has_no_permission" do
  253 + target = fast_create(profile_class)
246 254
247 - should 'create task in a enterprise' do  
248 - enterprise = fast_create(Enterprise)  
249 - give_permission(person, 'perform_task', enterprise)  
250 - post "/api/v1/enterprises/#{enterprise.id}/tasks?#{params.to_query}"  
251 - json = JSON.parse(last_response.body)  
252 - assert_not_nil json["task"]["id"] 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
253 end 290 end
254 291
255 - should 'not create task in a enterprise for unlogged users' do  
256 - logout_api  
257 - enterprise = fast_create(Enterprise)  
258 - give_permission(person, 'perform_task', enterprise)  
259 - post "/api/v1/enterprises/#{enterprise.id}/tasks?#{params.to_query}" 292 + should 'list all tasks of user in people context' do
  293 + environment.add_admin(person)
  294 + t1 = create(Task, :requestor => person, :target => environment)
  295 +
  296 + community = fast_create(Community)
  297 + community.add_admin(person)
  298 + t2 = create(Task, :requestor => person, :target => community)
  299 +
  300 + t3 = create(Task, :requestor => person, :target => person)
  301 +
  302 + get "/api/v1/people/#{person.id}/tasks?#{params.to_query}"
260 json = JSON.parse(last_response.body) 303 json = JSON.parse(last_response.body)
261 - assert_equal 401, last_response.status 304 + assert_equivalent [t1.id, t2.id, t3.id], json["tasks"].map { |a| a["id"] }
262 end 305 end
263 306
264 - should 'create task defining the target as the enterprise' do  
265 - enterprise = fast_create(Enterprise)  
266 - enterprise.add_member(person) 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 )
267 311
268 - post "/api/v1/enterprises/#{enterprise.id}/tasks?#{params.to_query}"  
269 - json = JSON.parse(last_response.body) 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)
270 316
271 - assert_equal enterprise, Task.last.target 317 + t5 = create(Task, :requestor => person, :target => person)
  318 + t6 = create(Task, :requestor => person, :target => person, :status => Task::Status::FINISHED)
  319 +
  320 + get "/api/v1/people/#{person.id}/tasks?#{params.merge(:status => Task::Status::ACTIVE).to_query}"
  321 + json = JSON.parse(last_response.body)
  322 + assert_equivalent [t1.id, t3.id, t5.id], json["tasks"].map { |a| a["id"] }
272 end 323 end
273 324
274 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
@@ -479,6 +461,87 @@ class TaskTest &lt; ActiveSupport::TestCase @@ -479,6 +461,87 @@ class TaskTest &lt; ActiveSupport::TestCase
479 assert_equal person, t.reload.closed_by 461 assert_equal person, t.reload.closed_by
480 end 462 end
481 463
  464 + should 'named scope to get tasks of a profile' do
  465 + requestor = fast_create(Person)
  466 + person = fast_create(Person)
  467 + another_person = fast_create(Person)
  468 + t1 = create(Task, :requestor => requestor, :target => person)
  469 + t2 = create(Task, :requestor => requestor, :target => another_person)
  470 + t3 = create(Task, :requestor => requestor, :target => person)
  471 +
  472 + assert_equivalent [t1,t3], Task.to(person)
  473 + end
  474 +
  475 + should 'named scope to get environment tasks if passed profile is environment admin' do
  476 + requestor = fast_create(Person)
  477 + person = fast_create(Person)
  478 + another_person = fast_create(Person)
  479 + environment = Environment.default
  480 + environment.add_admin(person)
  481 + t1 = create(Task, :requestor => requestor, :target => person)
  482 + t2 = create(Task, :requestor => requestor, :target => another_person)
  483 + t3 = create(Task, :requestor => requestor, :target => environment)
  484 +
  485 + assert_equivalent [t1,t3], Task.to(person)
  486 + end
  487 +
  488 + should 'named scope to not get environment tasks if passed profile is not environment admin' do
  489 + requestor = fast_create(Person)
  490 + person = fast_create(Person)
  491 + another_person = fast_create(Person)
  492 + environment = Environment.default
  493 + t1 = create(Task, :requestor => requestor, :target => person)
  494 + t2 = create(Task, :requestor => requestor, :target => another_person)
  495 + t3 = create(Task, :requestor => requestor, :target => environment)
  496 +
  497 + assert_equivalent [t1], Task.to(person)
  498 + end
  499 +
  500 + should 'named scope to get communities tasks if passed profile has perform_task permission' do
  501 + requestor = fast_create(Person)
  502 + person = fast_create(Person)
  503 + another_person = fast_create(Person)
  504 + community = fast_create(Community)
  505 + community.add_member(person)
  506 + person.expects(:has_permission?).with(:perform_task, community).returns(true)
  507 + t1 = create(Task, :requestor => requestor, :target => person)
  508 + t2 = create(Task, :requestor => requestor, :target => another_person)
  509 + t3 = create(Task, :requestor => requestor, :target => community)
  510 +
  511 + assert_equivalent [t1, t3], Task.to(person)
  512 + end
  513 +
  514 +
  515 + should 'named scope to not get communities tasks if passed profile has no perform_task permission in community' do
  516 + requestor = fast_create(Person)
  517 + person = fast_create(Person)
  518 + another_person = fast_create(Person)
  519 + community = fast_create(Community)
  520 + community.add_member(person)
  521 + person.expects(:has_permission?).with(:perform_task, community).returns(false)
  522 + t1 = create(Task, :requestor => requestor, :target => person)
  523 + t2 = create(Task, :requestor => requestor, :target => another_person)
  524 + t3 = create(Task, :requestor => requestor, :target => community)
  525 +
  526 + assert_equivalent [t1], Task.to(person)
  527 + end
  528 +
  529 + should 'named scope to return environment, person and communities tasks if user has 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 + environment = Environment.default
  537 + environment.add_admin(person)
  538 + t1 = create(Task, :requestor => requestor, :target => person)
  539 + t2 = create(Task, :requestor => requestor, :target => another_person)
  540 + t3 = create(Task, :requestor => requestor, :target => community)
  541 + t4 = create(Task, :requestor => requestor, :target => environment)
  542 + assert_equivalent [t1,t3,t4], Task.to(person)
  543 + end
  544 +
482 protected 545 protected
483 546
484 def sample_user 547 def sample_user