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 47 end
48 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 55 def make_conditions_with_parameter(params = {})
51 56 conditions = {}
52 57 from_date = DateTime.parse(params[:from]) if params[:from]
... ... @@ -64,9 +69,9 @@ module API
64 69 conditions = make_conditions_with_parameter(params)
65 70  
66 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 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 75 end
71 76 objects
72 77 end
... ...
lib/api/v1/articles.rb
... ... @@ -19,30 +19,28 @@ module API
19 19 # }
20 20 get do
21 21 articles = select_filtered_collection_of(environment, 'articles', params)
  22 + articles = articles.where(Article.display_filter(current_user.person, nil)[:conditions])
22 23 present articles, :with => Entities::Article
23 24 end
24 25  
25 26 desc "Return the article id"
26 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 30 end
29 31  
30 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 36 present articles, :with => Entities::Article
39 37 end
40 38  
41 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 42 end
44 43  
45   -
46 44 end
47 45  
48 46 resource :communities do
... ... @@ -51,12 +49,14 @@ module API
51 49 get do
52 50 community = environment.communities.find(params[:community_id])
53 51 articles = select_filtered_collection_of(community, 'articles', params)
  52 + articles = articles.where(Article.display_filter(current_user.person, community)[:conditions])
54 53 present articles, :with => Entities::Article
55 54 end
56 55  
57 56 get '/:id' do
58 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 60 end
61 61  
62 62 # Example Request:
... ...
test/unit/api_test.rb
... ... @@ -59,6 +59,16 @@ class APITest < ActiveSupport::TestCase
59 59 assert_includes json["articles"].map { |a| a["id"] }, article.id
60 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 72 should 'return article by id' do
63 73 article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
64 74 get "/api/v1/articles/#{article.id}?#{params.to_query}"
... ... @@ -66,6 +76,15 @@ class APITest < ActiveSupport::TestCase
66 76 assert_equal article.id, json["article"]["id"]
67 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 88 should 'return comments of an article' do
70 89 article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
71 90 article.comments.create!(:body => "some comment", :author => user.person)
... ... @@ -104,4 +123,74 @@ class APITest < ActiveSupport::TestCase
104 123 assert_equal category.name, json["category"]["name"]
105 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 196 end
... ...