diff --git a/app/models/task.rb b/app/models/task.rb index 1400e3e..cca9de3 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -265,6 +265,19 @@ class Task < ActiveRecord::Base include Spammable + #FIXME make this test + def display_to?(user = nil) + return true if self.target == user + return false if !self.target.kind_of?(Environment) && self.target.person? + + if self.target.kind_of?(Environment) + user.is_admin?(self.target) + else + self.target.members.by_role(self.target.roles.reject {|r| !r.has_permission?('perform_task')}).include?(user) + end + end + + protected # This method must be overrided in subclasses, and its implementation must do diff --git a/db/schema.rb b/db/schema.rb index 3dfc453..6c6cca1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -729,24 +729,26 @@ ActiveRecord::Schema.define(:version => 20150525101430) do create_table "users", :force => true do |t| t.string "login" t.string "email" - t.string "crypted_password", :limit => 40 - t.string "salt", :limit => 40 + t.string "crypted_password", :limit => 40 + t.string "salt", :limit => 40 t.datetime "created_at" t.datetime "updated_at" t.string "remember_token" t.datetime "remember_token_expires_at" t.text "terms_of_use" - t.string "terms_accepted", :limit => 1 + t.string "terms_accepted", :limit => 1 t.integer "environment_id" t.string "password_type" - t.boolean "enable_email", :default => false - t.string "last_chat_status", :default => "" - t.string "chat_status", :default => "" + t.boolean "enable_email", :default => false + t.string "last_chat_status", :default => "" + t.string "chat_status", :default => "" t.datetime "chat_status_at" - t.string "activation_code", :limit => 40 + t.string "activation_code", :limit => 40 t.datetime "activated_at" t.string "return_to" t.datetime "last_login_at" + t.string "private_token" + t.datetime "private_token_generated_at" end create_table "validation_infos", :force => true do |t| diff --git a/lib/noosfero/api/api.rb b/lib/noosfero/api/api.rb index b6c711d..a246549 100644 --- a/lib/noosfero/api/api.rb +++ b/lib/noosfero/api/api.rb @@ -44,6 +44,7 @@ module Noosfero mount V1::People mount V1::Enterprises mount V1::Categories + mount V1::Tasks mount Session # hook point which allow plugins to add Grape::API extensions to API::API diff --git a/lib/noosfero/api/entities.rb b/lib/noosfero/api/entities.rb index b1564a1..d911178 100644 --- a/lib/noosfero/api/entities.rb +++ b/lib/noosfero/api/entities.rb @@ -107,6 +107,7 @@ module Noosfero end class Task < Entity + root 'tasks', 'task' expose :id expose :type end diff --git a/lib/noosfero/api/helpers.rb b/lib/noosfero/api/helpers.rb index 28c15e6..c9f6f96 100644 --- a/lib/noosfero/api/helpers.rb +++ b/lib/noosfero/api/helpers.rb @@ -50,6 +50,11 @@ module Noosfero article.display_to?(current_user.person) ? article : forbidden! end + def find_task(tasks, id) + task = tasks.find(id) + task.display_to?(current_user.person) ? task : forbidden! + end + def make_conditions_with_parameter(params = {}) parsed_params = parser_params(params) conditions = {} diff --git a/lib/noosfero/api/v1/tasks.rb b/lib/noosfero/api/v1/tasks.rb new file mode 100644 index 0000000..0eda601 --- /dev/null +++ b/lib/noosfero/api/v1/tasks.rb @@ -0,0 +1,164 @@ +module Noosfero + module API + module V1 + class Tasks < Grape::API +# before { authenticate! } + +# ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} + + resource :tasks do + + # Collect tasks + # + # Parameters: + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created + # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected + # limit - amount of articles returned. The default value is 20 + # + # Example Request: + # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 + get do + #FIXME check for permission + tasks = select_filtered_collection_of(environment, 'tasks', params) + present tasks, :with => Entities::Task, :fields => params[:fields] + end + + desc "Return the task id" + get ':id' do + task = find_task(environment.tasks, params[:id]) + present task, :with => Entities::Task, :fields => params[:fields] + end + + + end + + resource :communities do + segment '/:community_id' do + resource :tasks do + get do + #FIXME check for permission + community = environment.communities.find(params[:community_id]) + tasks = select_filtered_collection_of(community, 'tasks', params) + present tasks, :with => Entities::Task, :fields => params[:fields] + end + + get ':id' do + community = environment.communities.find(params[:community_id]) + task = find_task(community.tasks, params[:id]) + present task, :with => Entities::Task, :fields => params[:fields] + end + + # Example Request: + # POST api/v1/communites/:community_id/articles?private_token=234298743290432&article[name]=title&article[body]=body + post do + community = environment.communities.find(params[:community_id]) +#FIXME see the correct permission + return forbidden! unless current_person.can_post_content?(community) +#FIXME check the task type before create + klass_type= params[:content_type].nil? ? 'Task' : params[:content_type] +# return forbidden! unless ARTICLE_TYPES.include?(klass_type) +# + task = klass_type.constantize.new(params[:task]) + task.requestor = current_person + task.target = community + + if !task.save + render_api_errors!(task.errors.full_messages) + end + present task, :with => Entities::Task, :fields => params[:fields] + end + + end + end + + end + + resource :people do + segment '/:person_id' do + resource :tasks do + get do +# person = environment.people.find(params[:person_id]) +# articles = select_filtered_collection_of(person, 'articles', params) +# articles = articles.display_filter(current_person, person) +tasks = Task.all + present tasks, :with => Entities::Task, :fields => params[:fields] + end + + get ':id' do +# person = environment.people.find(params[:person_id]) +# article = find_article(person.articles, params[:id]) +task = Task.first + present task, :with => Entities::Task, :fields => params[:fields] + end + + post do +# person = environment.people.find(params[:person_id]) +# return forbidden! unless current_person.can_post_content?(person) +# +# klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] +# return forbidden! unless ARTICLE_TYPES.include?(klass_type) +# +# article = klass_type.constantize.new(params[:article]) +# article.last_changed_by = current_person +# article.created_by= current_person +# article.profile = person +# +# if !article.save +# render_api_errors!(article.errors.full_messages) +# end +task = Task.first + present task, :with => Entities::Task, :fields => params[:fields] + end + + end + end + + end + + resource :enterprises do + segment '/:enterprise_id' do + resource :tasks do + get do +# enterprise = environment.enterprises.find(params[:enterprise_id]) +# articles = select_filtered_collection_of(enterprise, 'articles', params) +# articles = articles.display_filter(current_person, enterprise) +tasks = Task.all + present tasks, :with => Entities::Task, :fields => params[:fields] + end + + get ':id' do +# enterprise = environment.enterprises.find(params[:enterprise_id]) +# article = find_article(enterprise.articles, params[:id]) +task = Task.first + present task, :with => Entities::Task, :fields => params[:fields] + end + + post do +# enterprise = environment.enterprises.find(params[:enterprise_id]) +# return forbidden! unless current_person.can_post_content?(enterprise) +# +# klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] +# return forbidden! unless ARTICLE_TYPES.include?(klass_type) +# +# article = klass_type.constantize.new(params[:article]) +# article.last_changed_by = current_person +# article.created_by= current_person +# article.profile = enterprise +# +# if !article.save +# render_api_errors!(article.errors.full_messages) +# end +task = Task.first + present task, :with => Entities::Task, :fields => params[:fields] + end + + end + end + + end + + + end + end + end +end diff --git a/test/unit/api/task_test.rb b/test/unit/api/task_test.rb new file mode 100644 index 0000000..4fc6e87 --- /dev/null +++ b/test/unit/api/task_test.rb @@ -0,0 +1,389 @@ +require File.dirname(__FILE__) + '/test_helper' + +class TasksTest < ActiveSupport::TestCase + + def setup + login_api + @person = user.person + @community = fast_create(Community) + @environment = Environment.default + end + + attr_accessor :person, :community, :environment + + should 'list tasks' do + task = fast_create(Task, :requestor_id => environment.id, :target_id => community.id) + get "/api/v1/tasks?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_includes json["tasks"].map { |a| a["id"] }, task.id + end + + should 'return environment task by id' do + environment.add_admin(person) + task = create(Task, :requestor => person, :target => environment) + get "/api/v1/tasks/#{task.id}?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_equal task.id, json["task"]["id"] + end + + should 'not return environmet task if user has no permission to view it' do + person = fast_create(Person) + task = create(Task, :requestor => person, :target => environment) + + get "/api/v1/tasks/#{task.id}?#{params.to_query}" + assert_equal 403, last_response.status + end + + ############################# + # Community Tasks # + ############################# + + should 'return task by community' do + community = fast_create(Community) + task = create(Task, :requestor => person, :target => community) + get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_equal task.id, json["task"]["id"] + end + + should 'not return task by community if user has no permission to view it' do + community = fast_create(Community) + task = create(Task, :requestor => person, :target => community) + assert !person.is_member_of?(community) + + get "/api/v1/communities/#{community.id}/tasks/#{task.id}?#{params.to_query}" + assert_equal 403, last_response.status + end + +# should 'not list forbidden article when listing articles by community' do +# community = fast_create(Community) +# article = fast_create(Article, :profile_id => community.id, :name => "Some thing", :published => false) +# assert !article.published? +# +# get "/api/v1/communities/#{community.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_not_includes json['articles'].map {|a| a['id']}, article.id +# end + + should 'create task in a community' do + community = fast_create(Community) + give_permission(person, 'post_content', community) + post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_not_nil json["task"]["id"] + end + + should 'do not create article if user has no permission to post content' do +assert false +# community = fast_create(Community) +# give_permission(user.person, 'invite_members', community) +# params[:article] = {:name => "Title"} +# post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" +# assert_equal 403, last_response.status + end + +# should 'create article with parent' do +# community = fast_create(Community) +# community.add_member(user.person) +# article = fast_create(Article) +# +# params[:article] = {:name => "Title", :parent_id => article.id} +# post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal article.id, json["article"]["parent"]["id"] +# end + + should 'create task defining the requestor as current profile logged in' do + community = fast_create(Community) + community.add_member(person) + + post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}" + json = JSON.parse(last_response.body) + + assert_equal person, Task.last.requestor + end + + should 'create task defining the target as the community' do + community = fast_create(Community) + community.add_member(person) + + post "/api/v1/communities/#{community.id}/tasks?#{params.to_query}" + json = JSON.parse(last_response.body) + + assert_equal community, Task.last.target + end + +# ############################# +# # Person Articles # +# ############################# +# +# should 'return article by person' do +# person = fast_create(Person) +# article = fast_create(Article, :profile_id => person.id, :name => "Some thing") +# get "/api/v1/people/#{person.id}/articles/#{article.id}?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal article.id, json["article"]["id"] +# end +# +# should 'not return article by person if user has no permission to view it' do +# person = fast_create(Person) +# article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) +# assert !article.published? +# +# get "/api/v1/people/#{person.id}/articles/#{article.id}?#{params.to_query}" +# assert_equal 403, last_response.status +# end +# +# should 'not list forbidden article when listing articles by person' do +# person = fast_create(Person) +# article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) +# assert !article.published? +# get "/api/v1/people/#{person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_not_includes json['articles'].map {|a| a['id']}, article.id +# end +# +# should 'create article in a person' do +# params[:article] = {:name => "Title"} +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal "Title", json["article"]["title"] +# end +# +# should 'person do not create article if user has no permission to post content' do +# person = fast_create(Person) +# params[:article] = {:name => "Title"} +# post "/api/v1/people/#{person.id}/articles?#{params.to_query}" +# assert_equal 403, last_response.status +# end +# +# should 'person create article with parent' do +# article = fast_create(Article) +# +# params[:article] = {:name => "Title", :parent_id => article.id} +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal article.id, json["article"]["parent"]["id"] +# end +# +# should 'person create article with content type passed as parameter' do +# Article.delete_all +# params[:article] = {:name => "Title"} +# params[:content_type] = 'TextArticle' +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_kind_of TextArticle, Article.last +# end +# +# should 'person create article of TinyMceArticle type if no content type is passed as parameter' do +# params[:article] = {:name => "Title"} +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_kind_of TinyMceArticle, Article.last +# end +# +# should 'person not create article with invalid article content type' do +# params[:article] = {:name => "Title"} +# params[:content_type] = 'Person' +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal 403, last_response.status +# end +# +# should 'person create article defining the correct profile' do +# params[:article] = {:name => "Title"} +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal user.person, Article.last.profile +# end +# +# should 'person create article defining the created_by' do +# params[:article] = {:name => "Title"} +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal user.person, Article.last.created_by +# end +# +# should 'person create article defining the last_changed_by' do +# params[:article] = {:name => "Title"} +# post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal user.person, Article.last.last_changed_by +# end +# +# ############################# +# # Enterprise Articles # +# ############################# +# +# should 'return article by enterprise' do +# enterprise = fast_create(Enterprise) +# article = fast_create(Article, :profile_id => enterprise.id, :name => "Some thing") +# get "/api/v1/enterprises/#{enterprise.id}/articles/#{article.id}?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal article.id, json["article"]["id"] +# end +# +# should 'not return article by enterprise if user has no permission to view it' do +# enterprise = fast_create(Enterprise) +# article = fast_create(Article, :profile_id => enterprise.id, :name => "Some thing", :published => false) +# assert !article.published? +# +# get "/api/v1/enterprises/#{enterprise.id}/articles/#{article.id}?#{params.to_query}" +# assert_equal 403, last_response.status +# end +# +# should 'not list forbidden article when listing articles by enterprise' do +# enterprise = fast_create(Enterprise) +# article = fast_create(Article, :profile_id => enterprise.id, :name => "Some thing", :published => false) +# assert !article.published? +# +# get "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_not_includes json['articles'].map {|a| a['id']}, article.id +# end +# +# should 'create article in a enterprise' do +# enterprise = fast_create(Enterprise) +# give_permission(user.person, 'post_content', enterprise) +# params[:article] = {:name => "Title"} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal "Title", json["article"]["title"] +# end +# +# should 'enterprise: do not create article if user has no permission to post content' do +# enterprise = fast_create(Enterprise) +# give_permission(user.person, 'invite_members', enterprise) +# params[:article] = {:name => "Title"} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# assert_equal 403, last_response.status +# end +# +# should 'enterprise: create article with parent' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# article = fast_create(Article) +# +# params[:article] = {:name => "Title", :parent_id => article.id} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal article.id, json["article"]["parent"]["id"] +# end +# +# should 'enterprise: create article with content type passed as parameter' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# +# Article.delete_all +# params[:article] = {:name => "Title"} +# params[:content_type] = 'TextArticle' +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_kind_of TextArticle, Article.last +# end +# +# should 'enterprise: create article of TinyMceArticle type if no content type is passed as parameter' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# +# params[:article] = {:name => "Title"} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_kind_of TinyMceArticle, Article.last +# end +# +# should 'enterprise: not create article with invalid article content type' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# +# params[:article] = {:name => "Title"} +# params[:content_type] = 'Person' +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal 403, last_response.status +# end +# +# should 'enterprise: create article defining the correct profile' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# +# params[:article] = {:name => "Title"} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal enterprise, Article.last.profile +# end +# +# should 'enterprise: create article defining the created_by' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# +# params[:article] = {:name => "Title"} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal user.person, Article.last.created_by +# end +# +# should 'enterprise: create article defining the last_changed_by' do +# enterprise = fast_create(Enterprise) +# enterprise.add_member(user.person) +# +# params[:article] = {:name => "Title"} +# post "/api/v1/enterprises/#{enterprise.id}/articles?#{params.to_query}" +# json = JSON.parse(last_response.body) +# +# assert_equal user.person, Article.last.last_changed_by +# end +# +# should 'list article children with partial fields' do +# article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") +# child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing") +# params[:fields] = [:title] +# get "/api/v1/articles/#{article.id}/children?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal ['title'], json['articles'].first.keys +# end +# +# should 'suggest article children' do +# article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") +# params[:target_id] = user.person.id +# params[:article] = {:name => "Article name", :body => "Article body"} +# assert_difference "SuggestArticle.count" do +# post "/api/v1/articles/#{article.id}/children/suggest?#{params.to_query}" +# end +# json = JSON.parse(last_response.body) +# assert_equal 'SuggestArticle', json['type'] +# end +# +# should 'suggest event children' do +# article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") +# params[:target_id] = user.person.id +# params[:article] = {:name => "Article name", :body => "Article body", :type => "Event"} +# assert_difference "SuggestArticle.count" do +# post "/api/v1/articles/#{article.id}/children/suggest?#{params.to_query}" +# end +# json = JSON.parse(last_response.body) +# assert_equal 'SuggestArticle', json['type'] +# end +# +# should 'update hit attribute of article children' do +# a1 = fast_create(Article, :profile_id => user.person.id) +# a2 = fast_create(Article, :parent_id => a1.id, :profile_id => user.person.id) +# a3 = fast_create(Article, :parent_id => a1.id, :profile_id => user.person.id) +# get "/api/v1/articles/#{a1.id}/children?#{params.to_query}" +# json = JSON.parse(last_response.body) +# assert_equal [1, 1], json['articles'].map { |a| a['hits']} +# assert_equal [0, 1, 1], [a1.reload.hits, a2.reload.hits, a3.reload.hits] +# end +# +end -- libgit2 0.21.2