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 | ... | ... |