Commit 4bfa4aaae5e636c392779411c3c640c008e59f0d
Exists in
staging
and in
9 other branches
Merge branch 'all_pending_tasks_api' into 'master'
api: list all pending tasks for the current person See merge request !979
Showing
8 changed files
with
357 additions
and
195 deletions
Show diff stats
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 'tempfile' |
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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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
test/unit/task_test.rb
... | ... | @@ -324,24 +324,6 @@ class TaskTest < 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 < 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 | ... | ... |