Commit 61f22eb0ba786be3926d10c35ed91c0cc2fa3c22

Authored by Victor Costa
Committed by Rodrigo Souto
1 parent 43a4ef00

api: prevent users to access forbidden articles

lib/api/helpers.rb
@@ -47,6 +47,11 @@ module API @@ -47,6 +47,11 @@ module API
47 end 47 end
48 end 48 end
49 49
  50 + def find_article(articles, id)
  51 + article = articles.find(id)
  52 + article.display_to?(current_user.person) ? article : forbidden!
  53 + end
  54 +
50 def make_conditions_with_parameter(params = {}) 55 def make_conditions_with_parameter(params = {})
51 conditions = {} 56 conditions = {}
52 from_date = DateTime.parse(params[:from]) if params[:from] 57 from_date = DateTime.parse(params[:from]) if params[:from]
@@ -64,9 +69,9 @@ module API @@ -64,9 +69,9 @@ module API
64 conditions = make_conditions_with_parameter(params) 69 conditions = make_conditions_with_parameter(params)
65 70
66 if params[:reference_id] 71 if params[:reference_id]
67 - objects = object.send(method).send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).find(:all, :conditions => conditions, :limit => limit, :order => "created_at DESC") 72 + objects = object.send(method).send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).where(conditions).limit(limit).order("created_at DESC")
68 else 73 else
69 - objects = object.send(method).find(:all, :conditions => conditions, :limit => limit, :order => "created_at DESC") 74 + objects = object.send(method).where(conditions).limit(limit).order("created_at DESC")
70 end 75 end
71 objects 76 objects
72 end 77 end
lib/api/v1/articles.rb
@@ -19,30 +19,28 @@ module API @@ -19,30 +19,28 @@ module API
19 # } 19 # }
20 get do 20 get do
21 articles = select_filtered_collection_of(environment, 'articles', params) 21 articles = select_filtered_collection_of(environment, 'articles', params)
  22 + articles = articles.where(Article.display_filter(current_user.person, nil)[:conditions])
22 present articles, :with => Entities::Article 23 present articles, :with => Entities::Article
23 end 24 end
24 25
25 desc "Return the article id" 26 desc "Return the article id"
26 get ':id' do 27 get ':id' do
27 - present environment.articles.find(params[:id]), :with => Entities::Article 28 + article = find_article(environment.articles, params[:id])
  29 + present article, :with => Entities::Article
28 end 30 end
29 31
30 get ':id/children' do 32 get ':id/children' do
31 -  
32 - conditions = make_conditions_with_parameter(params)  
33 - if params[:reference_id]  
34 - articles = environment.articles.find(params[:id]).children.send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).find(:all, :conditions => conditions, :limit => limit, :order => "created_at DESC")  
35 - else  
36 - articles = environment.articles.find(params[:id]).children.find(:all, :conditions => conditions, :limit => limit, :order => "created_at DESC")  
37 - end 33 + article = find_article(environment.articles, params[:id])
  34 + articles = select_filtered_collection_of(article, 'children', params)
  35 + articles = articles.where(Article.display_filter(current_user.person, nil)[:conditions])
38 present articles, :with => Entities::Article 36 present articles, :with => Entities::Article
39 end 37 end
40 38
41 get ':id/children/:child_id' do 39 get ':id/children/:child_id' do
42 - present environment.articles.find(params[:id]).children.find(params[:child_id]), :with => Entities::Article 40 + article = find_article(environment.articles, params[:id])
  41 + present find_article(article.children, params[:child_id]), :with => Entities::Article
43 end 42 end
44 43
45 -  
46 end 44 end
47 45
48 resource :communities do 46 resource :communities do
@@ -51,12 +49,14 @@ module API @@ -51,12 +49,14 @@ module API
51 get do 49 get do
52 community = environment.communities.find(params[:community_id]) 50 community = environment.communities.find(params[:community_id])
53 articles = select_filtered_collection_of(community, 'articles', params) 51 articles = select_filtered_collection_of(community, 'articles', params)
  52 + articles = articles.where(Article.display_filter(current_user.person, community)[:conditions])
54 present articles, :with => Entities::Article 53 present articles, :with => Entities::Article
55 end 54 end
56 55
57 get '/:id' do 56 get '/:id' do
58 community = environment.communities.find(params[:community_id]) 57 community = environment.communities.find(params[:community_id])
59 - present community.articles.find(params[:id]), :with => Entities::Article 58 + article = find_article(community.articles, params[:id])
  59 + present article, :with => Entities::Article
60 end 60 end
61 61
62 # Example Request: 62 # Example Request:
test/unit/api_test.rb
@@ -59,6 +59,16 @@ class APITest < ActiveSupport::TestCase @@ -59,6 +59,16 @@ class APITest < ActiveSupport::TestCase
59 assert_includes json["articles"].map { |a| a["id"] }, article.id 59 assert_includes json["articles"].map { |a| a["id"] }, article.id
60 end 60 end
61 61
  62 + should 'not list forbidden article when listing articles' do
  63 + person = fast_create(Person)
  64 + article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
  65 + assert !article.published?
  66 +
  67 + get "/api/v1/articles?#{params.to_query}"
  68 + json = JSON.parse(last_response.body)
  69 + assert_not_includes json['articles'].map {|a| a['id']}, article.id
  70 + end
  71 +
62 should 'return article by id' do 72 should 'return article by id' do
63 article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") 73 article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
64 get "/api/v1/articles/#{article.id}?#{params.to_query}" 74 get "/api/v1/articles/#{article.id}?#{params.to_query}"
@@ -66,6 +76,15 @@ class APITest < ActiveSupport::TestCase @@ -66,6 +76,15 @@ class APITest < ActiveSupport::TestCase
66 assert_equal article.id, json["article"]["id"] 76 assert_equal article.id, json["article"]["id"]
67 end 77 end
68 78
  79 + should 'not return article if user has no permission to view it' do
  80 + person = fast_create(Person)
  81 + article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
  82 + assert !article.published?
  83 +
  84 + get "/api/v1/articles/#{article.id}?#{params.to_query}"
  85 + assert_equal 403, last_response.status
  86 + end
  87 +
69 should 'return comments of an article' do 88 should 'return comments of an article' do
70 article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") 89 article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
71 article.comments.create!(:body => "some comment", :author => user.person) 90 article.comments.create!(:body => "some comment", :author => user.person)
@@ -104,4 +123,74 @@ class APITest < ActiveSupport::TestCase @@ -104,4 +123,74 @@ class APITest < ActiveSupport::TestCase
104 assert_equal category.name, json["category"]["name"] 123 assert_equal category.name, json["category"]["name"]
105 end 124 end
106 125
  126 + should 'return article by community' do
  127 + community = fast_create(Community)
  128 + article = fast_create(Article, :profile_id => community.id, :name => "Some thing")
  129 + get "/api/v1/communities/#{community.id}/articles/#{article.id}?#{params.to_query}"
  130 + json = JSON.parse(last_response.body)
  131 + assert_equal article.id, json["article"]["id"]
  132 + end
  133 +
  134 + should 'not return article by community if user has no permission to view it' do
  135 + community = fast_create(Community)
  136 + article = fast_create(Article, :profile_id => community.id, :name => "Some thing", :published => false)
  137 + assert !article.published?
  138 +
  139 + get "/api/v1/communities/#{community.id}/articles/#{article.id}?#{params.to_query}"
  140 + assert_equal 403, last_response.status
  141 + end
  142 +
  143 + should 'not list forbidden article when listing articles by community' do
  144 + community = fast_create(Community)
  145 + article = fast_create(Article, :profile_id => community.id, :name => "Some thing", :published => false)
  146 + assert !article.published?
  147 +
  148 + get "/api/v1/communities/#{community.id}/articles?#{params.to_query}"
  149 + json = JSON.parse(last_response.body)
  150 + assert_not_includes json['articles'].map {|a| a['id']}, article.id
  151 + end
  152 +
  153 + should 'list article children' do
  154 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  155 + child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing")
  156 + child2 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing")
  157 + get "/api/v1/articles/#{article.id}/children?#{params.to_query}"
  158 + json = JSON.parse(last_response.body)
  159 + assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] }
  160 + end
  161 +
  162 + should 'not list children of forbidden article' do
  163 + person = fast_create(Person)
  164 + article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
  165 + child1 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
  166 + child2 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
  167 + get "/api/v1/articles/#{article.id}/children?#{params.to_query}"
  168 + assert_equal 403, last_response.status
  169 + end
  170 +
  171 + should 'not return child of forbidden article' do
  172 + person = fast_create(Person)
  173 + article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
  174 + child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
  175 + get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}"
  176 + assert_equal 403, last_response.status
  177 + end
  178 +
  179 + should 'not return private child' do
  180 + person = fast_create(Person)
  181 + article = fast_create(Article, :profile_id => person.id, :name => "Some thing")
  182 + child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false)
  183 + get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}"
  184 + assert_equal 403, last_response.status
  185 + end
  186 +
  187 + should 'not list private child' do
  188 + person = fast_create(Person)
  189 + article = fast_create(Article, :profile_id => person.id, :name => "Some thing")
  190 + child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false)
  191 + get "/api/v1/articles/#{article.id}/children?#{params.to_query}"
  192 + json = JSON.parse(last_response.body)
  193 + assert_not_includes json['articles'].map {|a| a['id']}, child.id
  194 + end
  195 +
107 end 196 end