Commit 4bfa4aaae5e636c392779411c3c640c008e59f0d

Authored by Victor Costa
2 parents 98f67e15 742a886d

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 263 root 'tasks', 'task'
264 264 expose :id
265 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 274 end
267 275  
268 276 class Environment < Entity
... ...
app/api/helpers.rb
... ... @@ -4,7 +4,7 @@ require &#39;tempfile&#39;
4 4 module Api
5 5 module Helpers
6 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 9 include SanitizeParams
10 10 include Noosfero::Plugin::HotSpot
... ... @@ -124,8 +124,8 @@ module Api
124 124 present_partial article, with: Entities::Article, params: params, current_person: current_person
125 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 129 present_articles(articles)
130 130 end
131 131  
... ... @@ -133,8 +133,8 @@ module Api
133 133 present_partial paginate(articles), :with => Entities::Article, :params => params, current_person: current_person
134 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 138 if current_person.present?
139 139 articles = articles.display_filter(current_person, nil)
140 140 else
... ... @@ -143,8 +143,9 @@ module Api
143 143 articles
144 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 149 not_found! if task.blank?
149 150 current_person.has_permission?(task.permission, asset) ? task : forbidden!
150 151 end
... ... @@ -152,6 +153,7 @@ module Api
152 153 def post_task(asset, params)
153 154 klass_type= params[:content_type].nil? ? 'Task' : params[:content_type]
154 155 return forbidden! unless klass_type.constantize <= Task
  156 + return forbidden! if !current_person.has_permission?(:perform_task, asset)
155 157  
156 158 task = klass_type.constantize.new(params[:task])
157 159 task.requestor_id = current_person.id
... ... @@ -164,15 +166,24 @@ module Api
164 166 present_partial task, :with => Entities::Task
165 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 178 present_partial task, :with => Entities::Task
170 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 187 present_partial tasks, :with => Entities::Task
177 188 end
178 189  
... ... @@ -181,7 +192,6 @@ module Api
181 192 conditions = {}
182 193 from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from]
183 194 until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until]
184   -
185 195 conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil?
186 196  
187 197 conditions[:created_at] = period(from_date, until_date) if from_date || until_date
... ... @@ -191,7 +201,7 @@ module Api
191 201 end
192 202  
193 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 205 order = "created_at DESC"
196 206 unless params[:order].blank?
197 207 if params[:order].include? '\'' or params[:order].include? '"'
... ... @@ -200,9 +210,9 @@ module Api
200 210 order = 'RANDOM()'
201 211 else
202 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 216 if direction.present? and ['ASC','DESC'].include? direction.upcase
207 217 order = "#{field_name} #{direction.upcase}"
208 218 end
... ... @@ -213,12 +223,14 @@ module Api
213 223 return order
214 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 227 timestamp = nil
218 228 if params[:timestamp]
219 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 234 end
223 235  
224 236 timestamp
... ... @@ -243,12 +255,12 @@ module Api
243 255 end
244 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 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 264 objects = by_reference(objects, params)
253 265 objects = by_categories(objects, params)
254 266  
... ... @@ -394,10 +406,27 @@ module Api
394 406 end
395 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 426 def parser_params(params)
398 427 parsed_params = {}
399 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 430 end
402 431 parsed_params
403 432 end
... ...
app/api/v1/tasks.rb
... ... @@ -3,9 +3,12 @@ module Api
3 3 class Tasks < Grape::API
4 4 before { authenticate! }
5 5  
  6 + MAX_PER_PAGE = 50
  7 +
6 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 13 # Parameters:
11 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 18 # Example Request:
16 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 20 get do
18   - present_tasks(environment)
  21 + tasks = Task.to(current_person)
  22 + present_tasks_for_asset(current_person, tasks)
19 23 end
20 24  
21 25 desc "Return the task id"
22 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 28 end
26 29  
27 30 %w[finish cancel].each do |action|
28 31 desc "#{action.capitalize} a task"
29 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 34 task.send(action, current_person) if (task.status == Task::Status::ACTIVE)
33 35 present_partial task, :with => Entities::Task
34 36 end
... ... @@ -42,7 +44,8 @@ module Api
42 44 resource :tasks do
43 45 get do
44 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 49 end
47 50  
48 51 get ':id' do
... ...
app/controllers/my_profile/tasks_controller.rb
... ... @@ -14,7 +14,7 @@ class TasksController &lt; MyProfileController
14 14 @filter_text = params[:filter_text].presence
15 15 @filter_responsible = params[:filter_responsible]
16 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 18 @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present?
19 19 @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
20 20 @failed = params ? params[:failed] : {}
... ... @@ -101,7 +101,7 @@ class TasksController &lt; MyProfileController
101 101 def search_tasks
102 102 filter_type = params[:filter_type].presence
103 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 106 render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} }
107 107 end
... ...
app/models/task.rb
... ... @@ -314,7 +314,7 @@ class Task &lt; ApplicationRecord
314 314 where "LOWER(#{field}) LIKE ?", "%#{value.downcase}%"
315 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 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 323 if profile.person?
324 324 envs_ids = Environment.all.select{ |env| profile.is_admin?(env) }.map{ |env| "target_id = #{env.id}"}.join(' OR ')
325 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 333 end
327 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 339 scope :from_closed_date, -> closed_from {
... ...
test/api/task_test.rb
... ... @@ -11,7 +11,7 @@ class TasksTest &lt; ActiveSupport::TestCase
11 11  
12 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 15 environment.add_admin(person)
16 16 task = create(Task, :requestor => person, :target => environment)
17 17 get "/api/v1/tasks?#{params.to_query}"
... ... @@ -50,144 +50,117 @@ class TasksTest &lt; ActiveSupport::TestCase
50 50 task = create(Task, :requestor => person, :target => environment)
51 51  
52 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 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 61 json = JSON.parse(last_response.body)
69   - assert_equal task.id, json["task"]["id"]
  62 + assert_equal t4.id, json["task"]["id"]
70 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 66 community = fast_create(Community)
75 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 73 json = JSON.parse(last_response.body)
82   - assert_equal 401, last_response.status
  74 + assert_equal t2.id, json["task"]["id"]
83 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 84 json = JSON.parse(last_response.body)
99   - assert_not_nil json["task"]["id"]
  85 + assert_equal t1.id, json["task"]["id"]
100 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 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 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 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 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 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 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 158 end
185 159  
186 160 task_actions=%w[finish cancel]
187 161 task_actions_state={"finish"=>"FINISHED","cancel"=>"CANCELLED"}
188 162 task_actions.each do |action|
189 163 should "person be able to #{action} his own task" do
190   - login_api
191 164 person1 = fast_create(Person)
192 165 task = create(Task, :requestor => person1, :target => person)
193 166 put "/api/v1/tasks/#{task.id}/#{action}?#{params.to_query}"
... ... @@ -195,8 +168,35 @@ class TasksTest &lt; ActiveSupport::TestCase
195 168 assert_equal "Task::Status::#{task_actions_state[action]}".constantize, task.reload.status
196 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 199 should "person not be able to #{action} other person's task" do
199   - login_api
200 200 user = fast_create(User)
201 201 person1 = fast_create(Person, :user_id => user)
202 202 task = create(Task, :requestor => person, :target => person1)
... ... @@ -206,69 +206,120 @@ class TasksTest &lt; ActiveSupport::TestCase
206 206 end
207 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 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 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 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 323 end
273 324  
274 325 end
... ...
test/unit/person_test.rb
... ... @@ -2005,4 +2005,5 @@ class PersonTest &lt; ActiveSupport::TestCase
2005 2005 person.remove_profile_from_circle(community, circle)
2006 2006 assert_equivalent [circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle)
2007 2007 end
  2008 +
2008 2009 end
... ...
test/unit/task_test.rb
... ... @@ -324,24 +324,6 @@ class TaskTest &lt; ActiveSupport::TestCase
324 324 task.activate
325 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 327 should 'filter tasks by type with scope' do
346 328 class CleanHouse < Task; end
347 329 class FeedDog < Task; end
... ... @@ -479,6 +461,87 @@ class TaskTest &lt; ActiveSupport::TestCase
479 461 assert_equal person, t.reload.closed_by
480 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 545 protected
483 546  
484 547 def sample_user
... ...