From 5da7a87ab15ef42c2fe7f62d96c3e47216382f22 Mon Sep 17 00:00:00 2001 From: Rodrigo Souto Date: Thu, 18 Jun 2015 19:07:40 -0300 Subject: [PATCH] api: refactoring articles api --- lib/noosfero/api/helpers.rb | 30 ++++++++++++++++++++++++++++++ lib/noosfero/api/v1/articles.rb | 133 ++++++++++++++++++------------------------------------------------------------------------------------------------------------------- test/unit/api/articles_test.rb | 380 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 3 files changed, 166 insertions(+), 377 deletions(-) diff --git a/lib/noosfero/api/helpers.rb b/lib/noosfero/api/helpers.rb index 35a3be4..5b79359 100644 --- a/lib/noosfero/api/helpers.rb +++ b/lib/noosfero/api/helpers.rb @@ -45,11 +45,41 @@ module Noosfero end end + ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} + def find_article(articles, id) article = articles.find(id) article.display_to?(current_user.person) ? article : forbidden! end + def post_article(asset, params) + return forbidden! unless current_person.can_post_content?(asset) + + 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 = asset + + if !article.save + render_api_errors!(article.errors.full_messages) + end + present article, :with => Entities::Article, :fields => params[:fields] + end + + def present_article(asset) + article = find_article(asset.articles, params[:id]) + present article, :with => Entities::Article, :fields => params[:fields] + end + + def present_articles(asset) + articles = select_filtered_collection_of(asset, 'articles', params) + articles = articles.display_filter(current_person, nil) + present articles, :with => Entities::Article, :fields => params[:fields] + end + def find_task(tasks, id) task = tasks.find(id) task.display_to?(current_user.person) ? task : forbidden! diff --git a/lib/noosfero/api/v1/articles.rb b/lib/noosfero/api/v1/articles.rb index b3d8d5f..bb6a6a7 100644 --- a/lib/noosfero/api/v1/articles.rb +++ b/lib/noosfero/api/v1/articles.rb @@ -18,15 +18,12 @@ module Noosfero # Example Request: # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 get do - articles = select_filtered_collection_of(environment, 'articles', params) - articles = articles.display_filter(current_person, nil) - present articles, :with => Entities::Article, :fields => params[:fields] + present_articles(environment) end desc "Return the article id" get ':id' do - article = find_article(environment.articles, params[:id]) - present article, :with => Entities::Article, :fields => params[:fields] + present_article(environment) end get ':id/children' do @@ -93,125 +90,31 @@ module Noosfero end - resource :communities do - segment '/:community_id' do - resource :articles do - get do - community = environment.communities.find(params[:community_id]) - articles = select_filtered_collection_of(community, 'articles', params) - articles = articles.display_filter(current_person, community) - present articles, :with => Entities::Article, :fields => params[:fields] - end - - get ':id' do - community = environment.communities.find(params[:community_id]) - article = find_article(community.articles, params[:id]) - present article, :with => Entities::Article, :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]) - return forbidden! unless current_person.can_post_content?(community) - - 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 = community - - if !article.save - render_api_errors!(article.errors.full_messages) + kinds = %w[community person enterprise] + kinds.each do |kind| + resource kind.pluralize.to_sym do + segment "/:#{kind}_id" do + resource :articles do + get do + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) + present_articles(profile) end - present article, :with => Entities::Article, :fields => params[:fields] - end - - end - end - - end - - resource :people do - segment '/:person_id' do - resource :articles 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) - present articles, :with => Entities::Article, :fields => params[:fields] - end - - get ':id' do - person = environment.people.find(params[:person_id]) - article = find_article(person.articles, params[:id]) - present article, :with => Entities::Article, :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) + get ':id' do + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) + present_article(profile) end - present article, :with => Entities::Article, :fields => params[:fields] - end - - end - end - - end - resource :enterprises do - segment '/:enterprise_id' do - resource :articles 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) - present articles, :with => Entities::Article, :fields => params[:fields] - end - - get ':id' do - enterprise = environment.enterprises.find(params[:enterprise_id]) - article = find_article(enterprise.articles, params[:id]) - present article, :with => Entities::Article, :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) + # Example Request: + # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body + post do + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) + post_article(profile, params) end - present article, :with => Entities::Article, :fields => params[:fields] end - end end - end - end end end diff --git a/test/unit/api/articles_test.rb b/test/unit/api/articles_test.rb index adc97ed..a9dcbd0 100644 --- a/test/unit/api/articles_test.rb +++ b/test/unit/api/articles_test.rb @@ -83,163 +83,147 @@ class ArticlesTest < ActiveSupport::TestCase end ############################# - # Community Articles # + # Profile Articles # ############################# - should 'return article by community' do - community = fast_create(Community) - article = fast_create(Article, :profile_id => community.id, :name => "Some thing") - get "/api/v1/communities/#{community.id}/articles/#{article.id}?#{params.to_query}" - json = JSON.parse(last_response.body) - assert_equal article.id, json["article"]["id"] - end + profile_kinds = %w(community person enterprise) + profile_kinds.each do |kind| + should "return article by #{kind}" do + profile = fast_create(kind.camelcase.constantize) + article = fast_create(Article, :profile_id => profile.id, :name => "Some thing") + get "/api/v1/#{kind.pluralize}/#{profile.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 community if user has no permission to view it' do - community = fast_create(Community) - article = fast_create(Article, :profile_id => community.id, :name => "Some thing", :published => false) - assert !article.published? + should "not return article by #{kind} if user has no permission to view it" do + profile = fast_create(kind.camelcase.constantize) + article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false) + assert !article.published? - get "/api/v1/communities/#{community.id}/articles/#{article.id}?#{params.to_query}" - assert_equal 403, last_response.status - end + get "/api/v1/#{kind.pluralize}/#{profile.id}/articles/#{article.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? + should "not list forbidden article when listing articles by #{kind}" do + profile = fast_create(kind.camelcase.constantize) + article = fast_create(Article, :profile_id => profile.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 + get "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_not_includes json['articles'].map {|a| a['id']}, article.id + end end - should 'create article in a community' do - community = fast_create(Community) - give_permission(user.person, 'post_content', community) - params[:article] = {:name => "Title"} - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - assert_equal "Title", json["article"]["title"] - end + ############################# + # Group Profile Articles # + ############################# - should 'do not create article if user has no permission to post content' do - 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 + group_kinds = %w(community enterprise) + group_kinds.each do |kind| + should "#{kind}: create article" do + profile = fast_create(kind.camelcase.constantize) + give_permission(user.person, 'post_content', profile) + params[:article] = {:name => "Title"} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_equal "Title", json["article"]["title"] + end - should 'create article with parent' do - community = fast_create(Community) - community.add_member(user.person) - article = fast_create(Article) + should "#{kind}: do not create article if user has no permission to post content" do + profile = fast_create(kind.camelcase.constantize) + give_permission(user.person, 'invite_members', profile) + params[:article] = {:name => "Title"} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + assert_equal 403, last_response.status + end - 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 "#{kind}: create article with parent" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) + article = fast_create(Article) - should 'create article with content type passed as parameter' do - community = fast_create(Community) - community.add_member(user.person) + params[:article] = {:name => "Title", :parent_id => article.id} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) + assert_equal article.id, json["article"]["parent"]["id"] + end - Article.delete_all - params[:article] = {:name => "Title"} - params[:content_type] = 'TextArticle' - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - - assert_kind_of TextArticle, Article.last - end - - should 'create article of TinyMceArticle type if no content type is passed as parameter' do - community = fast_create(Community) - community.add_member(user.person) + should "#{kind}: create article with content type passed as parameter" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) - params[:article] = {:name => "Title"} - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - - assert_kind_of TinyMceArticle, Article.last - end + Article.delete_all + params[:article] = {:name => "Title"} + params[:content_type] = 'TextArticle' + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) - should 'not create article with invalid article content type' do - community = fast_create(Community) - community.add_member(user.person) + assert_kind_of TextArticle, Article.last + end - params[:article] = {:name => "Title"} - params[:content_type] = 'Person' - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - - assert_equal 403, last_response.status - end + should "#{kind}: create article of TinyMceArticle type if no content type is passed as parameter" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) - should 'create article defining the correct profile' do - community = fast_create(Community) - community.add_member(user.person) + params[:article] = {:name => "Title"} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) - params[:article] = {:name => "Title"} - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - - assert_equal community, Article.last.profile - end + assert_kind_of TinyMceArticle, Article.last + end - should 'create article defining the created_by' do - community = fast_create(Community) - community.add_member(user.person) + should "#{kind}: not create article with invalid article content type" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) - params[:article] = {:name => "Title"} - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - - assert_equal user.person, Article.last.created_by - end + params[:article] = {:name => "Title"} + params[:content_type] = 'Person' + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) - should 'create article defining the last_changed_by' do - community = fast_create(Community) - community.add_member(user.person) + assert_equal 403, last_response.status + end - params[:article] = {:name => "Title"} - post "/api/v1/communities/#{community.id}/articles?#{params.to_query}" - json = JSON.parse(last_response.body) - - assert_equal user.person, Article.last.last_changed_by - end + should "#{kind}: create article defining the correct profile" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) - ############################# - # Person Articles # - ############################# + params[:article] = {:name => "Title"} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) - 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 + assert_equal profile, Article.last.profile + 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? + should "#{kind}: create article defining the created_by" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) - get "/api/v1/people/#{person.id}/articles/#{article.id}?#{params.to_query}" - assert_equal 403, last_response.status - end + params[:article] = {:name => "Title"} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) - 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 + assert_equal user.person, Article.last.created_by + end + + should "#{kind}: create article defining the last_changed_by" do + profile = fast_create(kind.camelcase.constantize) + profile.add_member(user.person) + + params[:article] = {:name => "Title"} + post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" + json = JSON.parse(last_response.body) + + assert_equal user.person, Article.last.last_changed_by + end end + ############################# + # Person Articles # + ############################# + should 'create article in a person' do params[:article] = {:name => "Title"} post "/api/v1/people/#{user.person.id}/articles?#{params.to_query}" @@ -269,15 +253,15 @@ class ArticlesTest < ActiveSupport::TestCase 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 @@ -286,7 +270,7 @@ class ArticlesTest < ActiveSupport::TestCase 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 @@ -294,7 +278,7 @@ class ArticlesTest < ActiveSupport::TestCase 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 @@ -302,7 +286,7 @@ class ArticlesTest < ActiveSupport::TestCase 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 @@ -310,135 +294,7 @@ class ArticlesTest < ActiveSupport::TestCase 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 -- libgit2 0.21.2