Commit 100df3575f11f2c551eb1e950440e3f648f19b98
1 parent
ea20a3dc
Exists in
web_steps_improvements
and in
8 other branches
API improvements
- changes pagination to use api-pagination gem - new endpoints to boxes, activities, and profiles - new exposed attributes for some entities - other minor changes Signed-off-by: Leandro Nunes dos Santos <leandronunes@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br> Signed-off-by: Victor Costa <vfcosta@gmail.com>
Showing
23 changed files
with
445 additions
and
61 deletions
Show diff stats
Gemfile
@@ -34,10 +34,11 @@ gem 'slim' | @@ -34,10 +34,11 @@ gem 'slim' | ||
34 | 34 | ||
35 | # API dependencies | 35 | # API dependencies |
36 | gem 'grape', '~> 0.12' | 36 | gem 'grape', '~> 0.12' |
37 | -gem 'grape-entity' | 37 | +gem 'grape-entity', '0.4.8' |
38 | gem 'grape_logging' | 38 | gem 'grape_logging' |
39 | gem 'rack-cors' | 39 | gem 'rack-cors' |
40 | gem 'rack-contrib' | 40 | gem 'rack-contrib' |
41 | +gem 'api-pagination', '~> 4.1.1' | ||
41 | 42 | ||
42 | # asset pipeline | 43 | # asset pipeline |
43 | gem 'uglifier', '>= 1.0.3' | 44 | gem 'uglifier', '>= 1.0.3' |
app/models/profile.rb
@@ -388,6 +388,10 @@ class Profile < ActiveRecord::Base | @@ -388,6 +388,10 @@ class Profile < ActiveRecord::Base | ||
388 | !profiles.exists? | 388 | !profiles.exists? |
389 | end | 389 | end |
390 | 390 | ||
391 | + def self.visible_for_person(person) | ||
392 | + self.all | ||
393 | + end | ||
394 | + | ||
391 | validates_presence_of :identifier, :name | 395 | validates_presence_of :identifier, :name |
392 | validates_length_of :nickname, :maximum => 16, :allow_nil => true | 396 | validates_length_of :nickname, :maximum => 16, :allow_nil => true |
393 | validate :valid_template | 397 | validate :valid_template |
lib/noosfero/api/api.rb
@@ -52,6 +52,9 @@ module Noosfero | @@ -52,6 +52,9 @@ module Noosfero | ||
52 | mount V1::Environments | 52 | mount V1::Environments |
53 | mount V1::Search | 53 | mount V1::Search |
54 | mount V1::Contacts | 54 | mount V1::Contacts |
55 | + mount V1::Boxes | ||
56 | + mount V1::Profiles | ||
57 | + mount V1::Activities | ||
55 | 58 | ||
56 | mount Session | 59 | mount Session |
57 | 60 |
lib/noosfero/api/entities.rb
@@ -79,6 +79,18 @@ module Noosfero | @@ -79,6 +79,18 @@ module Noosfero | ||
79 | expose :parent_id | 79 | expose :parent_id |
80 | end | 80 | end |
81 | 81 | ||
82 | + class Block < Entity | ||
83 | + root 'blocks', 'block' | ||
84 | + expose :id, :type, :settings, :position, :enabled | ||
85 | + expose :mirror, :mirror_block_id, :title | ||
86 | + end | ||
87 | + | ||
88 | + class Box < Entity | ||
89 | + root 'boxes', 'box' | ||
90 | + expose :id, :position | ||
91 | + expose :blocks, :using => Block | ||
92 | + end | ||
93 | + | ||
82 | class Profile < Entity | 94 | class Profile < Entity |
83 | expose :identifier, :name, :id | 95 | expose :identifier, :name, :id |
84 | expose :created_at, :format_with => :timestamp | 96 | expose :created_at, :format_with => :timestamp |
@@ -99,6 +111,7 @@ module Noosfero | @@ -99,6 +111,7 @@ module Noosfero | ||
99 | end | 111 | end |
100 | expose :image, :using => Image | 112 | expose :image, :using => Image |
101 | expose :region, :using => Region | 113 | expose :region, :using => Region |
114 | + expose :type | ||
102 | end | 115 | end |
103 | 116 | ||
104 | class UserBasic < Entity | 117 | class UserBasic < Entity |
@@ -109,6 +122,16 @@ module Noosfero | @@ -109,6 +122,16 @@ module Noosfero | ||
109 | class Person < Profile | 122 | class Person < Profile |
110 | root 'people', 'person' | 123 | root 'people', 'person' |
111 | expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' } | 124 | expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' } |
125 | + expose :vote_count | ||
126 | + expose :comments_count do |person, options| | ||
127 | + person.comments.count | ||
128 | + end | ||
129 | + expose :following_articles_count do |person, options| | ||
130 | + person.following_articles.count | ||
131 | + end | ||
132 | + expose :articles_count do |person, options| | ||
133 | + person.articles.count | ||
134 | + end | ||
112 | end | 135 | end |
113 | 136 | ||
114 | class Enterprise < Profile | 137 | class Enterprise < Profile |
@@ -149,6 +172,8 @@ module Noosfero | @@ -149,6 +172,8 @@ module Noosfero | ||
149 | expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"} | 172 | expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"} |
150 | expose :path | 173 | expose :path |
151 | expose :followers_count | 174 | expose :followers_count |
175 | + expose :votes_count | ||
176 | + expose :comments_count | ||
152 | end | 177 | end |
153 | 178 | ||
154 | class Article < ArticleBase | 179 | class Article < ArticleBase |
@@ -189,7 +214,7 @@ module Noosfero | @@ -189,7 +214,7 @@ module Noosfero | ||
189 | 214 | ||
190 | class UserLogin < User | 215 | class UserLogin < User |
191 | root 'users', 'user' | 216 | root 'users', 'user' |
192 | - expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'} | 217 | + expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}, if: lambda {|object, options| object.activated? } |
193 | end | 218 | end |
194 | 219 | ||
195 | class Task < Entity | 220 | class Task < Entity |
@@ -207,7 +232,15 @@ module Noosfero | @@ -207,7 +232,15 @@ module Noosfero | ||
207 | expose :name | 232 | expose :name |
208 | end | 233 | end |
209 | 234 | ||
210 | - | 235 | + class Activity < Entity |
236 | + root 'activities', 'activity' | ||
237 | + expose :id, :params, :verb, :created_at, :updated_at, :comments_count, :visible | ||
238 | + expose :user, :using => Profile | ||
239 | + expose :target do |activity, opts| | ||
240 | + type_map = {Profile => ::Profile, ArticleBase => ::Article}.find {|h| activity.target.kind_of?(h.last)} | ||
241 | + type_map.first.represent(activity.target) unless type_map.nil? | ||
242 | + end | ||
243 | + end | ||
211 | end | 244 | end |
212 | end | 245 | end |
213 | end | 246 | end |
lib/noosfero/api/entity.rb
@@ -22,18 +22,4 @@ class Noosfero::API::Entity < Grape::Entity | @@ -22,18 +22,4 @@ class Noosfero::API::Entity < Grape::Entity | ||
22 | end | 22 | end |
23 | end | 23 | end |
24 | 24 | ||
25 | - def self.fields_condition(fields) | ||
26 | - lambda do |object, options| | ||
27 | - return true if options[:fields].blank? | ||
28 | - fields.map { |field| options[:fields].include?(field.to_s)}.grep(true).present? | ||
29 | - end | ||
30 | - end | ||
31 | - | ||
32 | - def self.expose(*args, &block) | ||
33 | - hash = args.last.is_a?(Hash) ? args.pop : {} | ||
34 | - hash.merge!({:if => fields_condition(args)}) if hash[:if].blank? | ||
35 | - args << hash | ||
36 | - super | ||
37 | - end | ||
38 | - | ||
39 | end | 25 | end |
lib/noosfero/api/helpers.rb
@@ -5,7 +5,7 @@ require_relative '../../find_by_contents' | @@ -5,7 +5,7 @@ require_relative '../../find_by_contents' | ||
5 | module API | 5 | module API |
6 | module APIHelpers | 6 | module APIHelpers |
7 | PRIVATE_TOKEN_PARAM = :private_token | 7 | PRIVATE_TOKEN_PARAM = :private_token |
8 | - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id] | 8 | + DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier] |
9 | 9 | ||
10 | include SanitizeParams | 10 | include SanitizeParams |
11 | include Noosfero::Plugin::HotSpot | 11 | include Noosfero::Plugin::HotSpot |
@@ -38,6 +38,20 @@ require_relative '../../find_by_contents' | @@ -38,6 +38,20 @@ require_relative '../../find_by_contents' | ||
38 | @environment | 38 | @environment |
39 | end | 39 | end |
40 | 40 | ||
41 | + def present_partial(model, options) | ||
42 | + if(params[:fields].present?) | ||
43 | + begin | ||
44 | + fields = JSON.parse(params[:fields]) | ||
45 | + if fields.present? | ||
46 | + options.merge!(fields.symbolize_keys.slice(:only, :except)) | ||
47 | + end | ||
48 | + rescue | ||
49 | + options[:only] = Array.wrap(params[:fields]) | ||
50 | + end | ||
51 | + end | ||
52 | + present model, options | ||
53 | + end | ||
54 | + | ||
41 | include FindByContents | 55 | include FindByContents |
42 | 56 | ||
43 | #################################################################### | 57 | #################################################################### |
@@ -87,7 +101,7 @@ require_relative '../../find_by_contents' | @@ -87,7 +101,7 @@ require_relative '../../find_by_contents' | ||
87 | def post_article(asset, params) | 101 | def post_article(asset, params) |
88 | return forbidden! unless current_person.can_post_content?(asset) | 102 | return forbidden! unless current_person.can_post_content?(asset) |
89 | 103 | ||
90 | - klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | 104 | + klass_type= params[:content_type].nil? ? TinyMceArticle.name : params[:content_type] |
91 | return forbidden! unless ARTICLE_TYPES.include?(klass_type) | 105 | return forbidden! unless ARTICLE_TYPES.include?(klass_type) |
92 | 106 | ||
93 | article = klass_type.constantize.new(params[:article]) | 107 | article = klass_type.constantize.new(params[:article]) |
@@ -98,12 +112,12 @@ require_relative '../../find_by_contents' | @@ -98,12 +112,12 @@ require_relative '../../find_by_contents' | ||
98 | if !article.save | 112 | if !article.save |
99 | render_api_errors!(article.errors.full_messages) | 113 | render_api_errors!(article.errors.full_messages) |
100 | end | 114 | end |
101 | - present article, :with => Entities::Article, :fields => params[:fields] | 115 | + present_partial article, :with => Entities::Article |
102 | end | 116 | end |
103 | 117 | ||
104 | def present_article(asset) | 118 | def present_article(asset) |
105 | article = find_article(asset.articles, params[:id]) | 119 | article = find_article(asset.articles, params[:id]) |
106 | - present article, :with => Entities::Article, :fields => params[:fields] | 120 | + present_partial article, :with => Entities::Article |
107 | end | 121 | end |
108 | 122 | ||
109 | def present_articles_for_asset(asset, method = 'articles') | 123 | def present_articles_for_asset(asset, method = 'articles') |
@@ -112,7 +126,7 @@ require_relative '../../find_by_contents' | @@ -112,7 +126,7 @@ require_relative '../../find_by_contents' | ||
112 | end | 126 | end |
113 | 127 | ||
114 | def present_articles(articles) | 128 | def present_articles(articles) |
115 | - present articles, :with => Entities::Article, :fields => params[:fields] | 129 | + present_partial paginate(articles), :with => Entities::Article |
116 | end | 130 | end |
117 | 131 | ||
118 | def find_articles(asset, method = 'articles') | 132 | def find_articles(asset, method = 'articles') |
@@ -142,19 +156,19 @@ require_relative '../../find_by_contents' | @@ -142,19 +156,19 @@ require_relative '../../find_by_contents' | ||
142 | if !task.save | 156 | if !task.save |
143 | render_api_errors!(task.errors.full_messages) | 157 | render_api_errors!(task.errors.full_messages) |
144 | end | 158 | end |
145 | - present task, :with => Entities::Task, :fields => params[:fields] | 159 | + present_partial task, :with => Entities::Task |
146 | end | 160 | end |
147 | 161 | ||
148 | def present_task(asset) | 162 | def present_task(asset) |
149 | task = find_task(asset, params[:id]) | 163 | task = find_task(asset, params[:id]) |
150 | - present task, :with => Entities::Task, :fields => params[:fields] | 164 | + present_partial task, :with => Entities::Task |
151 | end | 165 | end |
152 | 166 | ||
153 | def present_tasks(asset) | 167 | def present_tasks(asset) |
154 | tasks = select_filtered_collection_of(asset, 'tasks', params) | 168 | tasks = select_filtered_collection_of(asset, 'tasks', params) |
155 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} | 169 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} |
156 | return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) | 170 | return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) |
157 | - present tasks, :with => Entities::Task, :fields => params[:fields] | 171 | + present_partial tasks, :with => Entities::Task |
158 | end | 172 | end |
159 | 173 | ||
160 | def make_conditions_with_parameter(params = {}) | 174 | def make_conditions_with_parameter(params = {}) |
@@ -194,15 +208,6 @@ require_relative '../../find_by_contents' | @@ -194,15 +208,6 @@ require_relative '../../find_by_contents' | ||
194 | return order | 208 | return order |
195 | end | 209 | end |
196 | 210 | ||
197 | - def make_page_number_with_parameters(params) | ||
198 | - params[:page] || 1 | ||
199 | - end | ||
200 | - | ||
201 | - def make_per_page_with_parameters(params) | ||
202 | - params[:per_page] ||= limit | ||
203 | - params[:per_page].to_i | ||
204 | - end | ||
205 | - | ||
206 | def make_timestamp_with_parameters_and_method(params, method) | 211 | def make_timestamp_with_parameters_and_method(params, method) |
207 | timestamp = nil | 212 | timestamp = nil |
208 | if params[:timestamp] | 213 | if params[:timestamp] |
@@ -236,17 +241,17 @@ require_relative '../../find_by_contents' | @@ -236,17 +241,17 @@ require_relative '../../find_by_contents' | ||
236 | def select_filtered_collection_of(object, method, params) | 241 | def select_filtered_collection_of(object, method, params) |
237 | conditions = make_conditions_with_parameter(params) | 242 | conditions = make_conditions_with_parameter(params) |
238 | order = make_order_with_parameters(object,method,params) | 243 | order = make_order_with_parameters(object,method,params) |
239 | - page_number = make_page_number_with_parameters(params) | ||
240 | - per_page = make_per_page_with_parameters(params) | ||
241 | timestamp = make_timestamp_with_parameters_and_method(params, method) | 244 | timestamp = make_timestamp_with_parameters_and_method(params, method) |
242 | 245 | ||
243 | objects = object.send(method) | 246 | objects = object.send(method) |
244 | objects = by_reference(objects, params) | 247 | objects = by_reference(objects, params) |
245 | objects = by_categories(objects, params) | 248 | objects = by_categories(objects, params) |
246 | 249 | ||
247 | - objects = objects.where(conditions).where(timestamp).page(page_number).per_page(per_page).reorder(order) | 250 | + objects = objects.where(conditions).where(timestamp).reorder(order) |
248 | 251 | ||
249 | - objects | 252 | + params[:page] ||= 1 |
253 | + params[:per_page] ||= limit | ||
254 | + paginate(objects) | ||
250 | end | 255 | end |
251 | 256 | ||
252 | def authenticate! | 257 | def authenticate! |
lib/noosfero/api/session.rb
@@ -24,6 +24,14 @@ module Noosfero | @@ -24,6 +24,14 @@ module Noosfero | ||
24 | present user, :with => Entities::UserLogin, :current_person => current_person | 24 | present user, :with => Entities::UserLogin, :current_person => current_person |
25 | end | 25 | end |
26 | 26 | ||
27 | + post "/login_from_cookie" do | ||
28 | + return unauthorized! if cookies[:auth_token].blank? | ||
29 | + user = User.where(remember_token: cookies[:auth_token]).first | ||
30 | + return unauthorized! unless user && user.activated? | ||
31 | + @current_user = user | ||
32 | + present user, :with => Entities::UserLogin, :current_person => current_person | ||
33 | + end | ||
34 | + | ||
27 | # Create user. | 35 | # Create user. |
28 | # | 36 | # |
29 | # Parameters: | 37 | # Parameters: |
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Activities < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :profiles do | ||
8 | + | ||
9 | + get ':id/activities' do | ||
10 | + profile = environment.profiles | ||
11 | + profile = profile.visible_for_person(current_person) if profile.respond_to?(:visible_for_person) | ||
12 | + profile = profile.find_by_id(params[:id]) | ||
13 | + activities = profile.activities.map(&:activity) | ||
14 | + present activities, :with => Entities::Activity, :current_person => current_person | ||
15 | + end | ||
16 | + end | ||
17 | + end | ||
18 | + end | ||
19 | + end | ||
20 | +end |
lib/noosfero/api/v1/articles.rb
@@ -5,8 +5,11 @@ module Noosfero | @@ -5,8 +5,11 @@ module Noosfero | ||
5 | 5 | ||
6 | ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} | 6 | ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} |
7 | 7 | ||
8 | + MAX_PER_PAGE = 50 | ||
9 | + | ||
8 | resource :articles do | 10 | resource :articles do |
9 | 11 | ||
12 | + paginate max_per_page: MAX_PER_PAGE | ||
10 | # Collect articles | 13 | # Collect articles |
11 | # | 14 | # |
12 | # Parameters: | 15 | # Parameters: |
@@ -49,7 +52,7 @@ module Noosfero | @@ -49,7 +52,7 @@ module Noosfero | ||
49 | article = environment.articles.find(params[:id]) | 52 | article = environment.articles.find(params[:id]) |
50 | return forbidden! unless article.allow_edit?(current_person) | 53 | return forbidden! unless article.allow_edit?(current_person) |
51 | article.update_attributes!(params[:article]) | 54 | article.update_attributes!(params[:article]) |
52 | - present article, :with => Entities::Article, :fields => params[:fields] | 55 | + present_partial article, :with => Entities::Article |
53 | end | 56 | end |
54 | 57 | ||
55 | desc 'Report a abuse and/or violent content in a article by id' do | 58 | desc 'Report a abuse and/or violent content in a article by id' do |
@@ -93,7 +96,7 @@ module Noosfero | @@ -93,7 +96,7 @@ module Noosfero | ||
93 | end | 96 | end |
94 | #FIXME refactor this method | 97 | #FIXME refactor this method |
95 | get 'voted_by_me' do | 98 | get 'voted_by_me' do |
96 | - present_articles(current_person.votes.collect(&:voteable)) | 99 | + present_articles(current_person.votes.where(:voteable_type => 'Article').collect(&:voteable)) |
97 | end | 100 | end |
98 | 101 | ||
99 | desc 'Perform a vote on a article by id' do | 102 | desc 'Perform a vote on a article by id' do |
@@ -108,8 +111,12 @@ module Noosfero | @@ -108,8 +111,12 @@ module Noosfero | ||
108 | # FIXME verify allowed values | 111 | # FIXME verify allowed values |
109 | render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value) | 112 | render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value) |
110 | article = find_article(environment.articles, params[:id]) | 113 | article = find_article(environment.articles, params[:id]) |
111 | - vote = Vote.new(:voteable => article, :voter => current_person, :vote => value) | ||
112 | - {:vote => vote.save} | 114 | + begin |
115 | + vote = Vote.new(:voteable => article, :voter => current_person, :vote => value) | ||
116 | + {:vote => vote.save!} | ||
117 | + rescue ActiveRecord::RecordInvalid => e | ||
118 | + render_api_error!(e.message, 400) | ||
119 | + end | ||
113 | end | 120 | end |
114 | 121 | ||
115 | desc "Returns the total followers for the article" do | 122 | desc "Returns the total followers for the article" do |
@@ -123,6 +130,11 @@ module Noosfero | @@ -123,6 +130,11 @@ module Noosfero | ||
123 | {:total_followers => total} | 130 | {:total_followers => total} |
124 | end | 131 | end |
125 | 132 | ||
133 | + desc "Return the articles followed by me" | ||
134 | + get 'followed_by_me' do | ||
135 | + present_articles_for_asset(current_person, 'following_articles') | ||
136 | + end | ||
137 | + | ||
126 | desc "Add a follower for the article" do | 138 | desc "Add a follower for the article" do |
127 | detail 'Add the current user identified by private token, like a follower of a article' | 139 | detail 'Add the current user identified by private token, like a follower of a article' |
128 | params Noosfero::API::Entities::UserLogin.documentation | 140 | params Noosfero::API::Entities::UserLogin.documentation |
@@ -150,6 +162,7 @@ module Noosfero | @@ -150,6 +162,7 @@ module Noosfero | ||
150 | named 'ArticleChildren' | 162 | named 'ArticleChildren' |
151 | end | 163 | end |
152 | 164 | ||
165 | + paginate per_page: MAX_PER_PAGE, max_per_page: MAX_PER_PAGE | ||
153 | get ':id/children' do | 166 | get ':id/children' do |
154 | article = find_article(environment.articles, params[:id]) | 167 | article = find_article(environment.articles, params[:id]) |
155 | 168 | ||
@@ -177,7 +190,7 @@ module Noosfero | @@ -177,7 +190,7 @@ module Noosfero | ||
177 | article = find_article(environment.articles, params[:id]) | 190 | article = find_article(environment.articles, params[:id]) |
178 | child = find_article(article.children, params[:child_id]) | 191 | child = find_article(article.children, params[:child_id]) |
179 | child.hit | 192 | child.hit |
180 | - present child, :with => Entities::Article, :fields => params[:fields] | 193 | + present_partial child, :with => Entities::Article |
181 | end | 194 | end |
182 | 195 | ||
183 | desc 'Suggest a article to another profile' do | 196 | desc 'Suggest a article to another profile' do |
@@ -200,7 +213,7 @@ module Noosfero | @@ -200,7 +213,7 @@ module Noosfero | ||
200 | unless suggest_article.save | 213 | unless suggest_article.save |
201 | render_api_errors!(suggest_article.article_object.errors.full_messages) | 214 | render_api_errors!(suggest_article.article_object.errors.full_messages) |
202 | end | 215 | end |
203 | - present suggest_article, :with => Entities::Task, :fields => params[:fields] | 216 | + present_partial suggest_article, :with => Entities::Task |
204 | end | 217 | end |
205 | 218 | ||
206 | # Example Request: | 219 | # Example Request: |
@@ -231,12 +244,21 @@ module Noosfero | @@ -231,12 +244,21 @@ module Noosfero | ||
231 | if !article.save | 244 | if !article.save |
232 | render_api_errors!(article.errors.full_messages) | 245 | render_api_errors!(article.errors.full_messages) |
233 | end | 246 | end |
234 | - present article, :with => Entities::Article, :fields => params[:fields] | 247 | + present_partial article, :with => Entities::Article |
235 | end | 248 | end |
236 | 249 | ||
237 | end | 250 | end |
238 | 251 | ||
239 | - kinds = %w[community person enterprise] | 252 | + resource :profiles do |
253 | + get ':id/home_page' do | ||
254 | + profiles = environment.profiles | ||
255 | + profiles = profiles.visible_for_person(current_person) | ||
256 | + profile = profiles.find_by_id(params[:id]) | ||
257 | + present_partial profile.home_page, :with => Entities::Article | ||
258 | + end | ||
259 | + end | ||
260 | + | ||
261 | + kinds = %w[profile community person enterprise] | ||
240 | kinds.each do |kind| | 262 | kinds.each do |kind| |
241 | resource kind.pluralize.to_sym do | 263 | resource kind.pluralize.to_sym do |
242 | segment "/:#{kind}_id" do | 264 | segment "/:#{kind}_id" do |
@@ -258,7 +280,7 @@ module Noosfero | @@ -258,7 +280,7 @@ module Noosfero | ||
258 | article = forbidden! | 280 | article = forbidden! |
259 | end | 281 | end |
260 | 282 | ||
261 | - present article, :with => Entities::Article, :fields => params[:fields] | 283 | + present_partial article, :with => Entities::Article |
262 | else | 284 | else |
263 | 285 | ||
264 | present_articles_for_asset(profile) | 286 | present_articles_for_asset(profile) |
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + | ||
5 | + class Boxes < Grape::API | ||
6 | + | ||
7 | + kinds = %w[profile community person enterprise] | ||
8 | + kinds.each do |kind| | ||
9 | + | ||
10 | + resource kind.pluralize.to_sym do | ||
11 | + | ||
12 | + segment "/:#{kind}_id" do | ||
13 | + resource :boxes do | ||
14 | + get do | ||
15 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
16 | + present profile.boxes, :with => Entities::Box | ||
17 | + end | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + end | ||
22 | + | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + end | ||
27 | + end | ||
28 | +end |
lib/noosfero/api/v1/comments.rb
@@ -31,7 +31,12 @@ module Noosfero | @@ -31,7 +31,12 @@ module Noosfero | ||
31 | post ":id/comments" do | 31 | post ":id/comments" do |
32 | article = find_article(environment.articles, params[:id]) | 32 | article = find_article(environment.articles, params[:id]) |
33 | options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article) | 33 | options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article) |
34 | - present Comment.create(options), :with => Entities::Comment, :current_person => current_person | 34 | + begin |
35 | + comment = Comment.create!(options) | ||
36 | + rescue ActiveRecord::RecordInvalid => e | ||
37 | + render_api_error!(e.message, 400) | ||
38 | + end | ||
39 | + present comment, :with => Entities::Comment, :current_person => current_person | ||
35 | end | 40 | end |
36 | end | 41 | end |
37 | 42 |
lib/noosfero/api/v1/people.rb
@@ -4,9 +4,12 @@ module Noosfero | @@ -4,9 +4,12 @@ module Noosfero | ||
4 | class People < Grape::API | 4 | class People < Grape::API |
5 | before { authenticate! } | 5 | before { authenticate! } |
6 | 6 | ||
7 | + MAX_PER_PAGE = 50 | ||
8 | + | ||
7 | desc 'API Root' | 9 | desc 'API Root' |
8 | 10 | ||
9 | resource :people do | 11 | resource :people do |
12 | + paginate max_per_page: MAX_PER_PAGE | ||
10 | 13 | ||
11 | # -- A note about privacy -- | 14 | # -- A note about privacy -- |
12 | # We wold find people by location, but we must test if the related | 15 | # We wold find people by location, but we must test if the related |
@@ -33,12 +36,12 @@ module Noosfero | @@ -33,12 +36,12 @@ module Noosfero | ||
33 | get do | 36 | get do |
34 | people = select_filtered_collection_of(environment, 'people', params) | 37 | people = select_filtered_collection_of(environment, 'people', params) |
35 | people = people.visible_for_person(current_person) | 38 | people = people.visible_for_person(current_person) |
36 | - present people, :with => Entities::Person, :current_person => current_person | 39 | + present_partial people, :with => Entities::Person, :current_person => current_person |
37 | end | 40 | end |
38 | 41 | ||
39 | desc "Return the logged user information" | 42 | desc "Return the logged user information" |
40 | get "/me" do | 43 | get "/me" do |
41 | - present current_person, :with => Entities::Person, :current_person => current_person | 44 | + present_partial current_person, :with => Entities::Person, :current_person => current_person |
42 | end | 45 | end |
43 | 46 | ||
44 | desc "Return the person information" | 47 | desc "Return the person information" |
@@ -105,6 +108,19 @@ module Noosfero | @@ -105,6 +108,19 @@ module Noosfero | ||
105 | present output | 108 | present output |
106 | end | 109 | end |
107 | end | 110 | end |
111 | + | ||
112 | + resource :profiles do | ||
113 | + segment '/:profile_id' do | ||
114 | + resource :members do | ||
115 | + paginate max_per_page: MAX_PER_PAGE | ||
116 | + get do | ||
117 | + profile = environment.profiles.find_by_id(params[:profile_id]) | ||
118 | + members = select_filtered_collection_of(profile, 'members', params) | ||
119 | + present members, :with => Entities::Person, :current_person => current_person | ||
120 | + end | ||
121 | + end | ||
122 | + end | ||
123 | + end | ||
108 | end | 124 | end |
109 | end | 125 | end |
110 | end | 126 | end |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Profiles < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :profiles do | ||
8 | + | ||
9 | + get do | ||
10 | + profiles = select_filtered_collection_of(environment, 'profiles', params) | ||
11 | + profiles = profiles.visible_for_person(current_person) | ||
12 | + profiles = profiles.by_location(params) # Must be the last. May return Exception obj. | ||
13 | + present profiles, :with => Entities::Profile, :current_person => current_person | ||
14 | + end | ||
15 | + | ||
16 | + get ':id' do | ||
17 | + profiles = environment.profiles | ||
18 | + profiles = profiles.visible_for_person(current_person) | ||
19 | + profile = profiles.find_by_id(params[:id]) | ||
20 | + present profile, :with => Entities::Profile, :current_person => current_person | ||
21 | + end | ||
22 | + end | ||
23 | + end | ||
24 | + end | ||
25 | + end | ||
26 | +end |
lib/noosfero/api/v1/search.rb
@@ -5,6 +5,7 @@ module Noosfero | @@ -5,6 +5,7 @@ module Noosfero | ||
5 | 5 | ||
6 | resource :search do | 6 | resource :search do |
7 | resource :article do | 7 | resource :article do |
8 | + paginate max_per_page: 200 | ||
8 | get do | 9 | get do |
9 | # Security checks | 10 | # Security checks |
10 | sanitize_params_hash(params) | 11 | sanitize_params_hash(params) |
@@ -15,24 +16,19 @@ module Noosfero | @@ -15,24 +16,19 @@ module Noosfero | ||
15 | profile = environment.profiles.find(params[:profile_id]) if params[:profile_id] | 16 | profile = environment.profiles.find(params[:profile_id]) if params[:profile_id] |
16 | scope = profile.nil? ? environment.articles.is_public : profile.articles.is_public | 17 | scope = profile.nil? ? environment.articles.is_public : profile.articles.is_public |
17 | scope = scope.where(:type => params[:type]) if params[:type] && !(params[:type] == 'Article') | 18 | scope = scope.where(:type => params[:type]) if params[:type] && !(params[:type] == 'Article') |
18 | - scope = scope.where(:parent_id => params[:parent_id]) if params[:parent_id].present? | 19 | + scope = scope.where(make_conditions_with_parameter(params)) |
19 | scope = scope.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present? | 20 | scope = scope.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present? |
21 | + scope = scope.where('articles.children_count > 0') if params[:has_children].present? | ||
20 | query = params[:query] || "" | 22 | query = params[:query] || "" |
21 | order = "more_recent" | 23 | order = "more_recent" |
22 | 24 | ||
23 | options = {:filter => order, :template_id => params[:template_id]} | 25 | options = {:filter => order, :template_id => params[:template_id]} |
24 | 26 | ||
25 | - paginate_options = params.select{|k,v| [:page, :per_page].include?(k.to_sym)}.symbolize_keys | ||
26 | - paginate_options.each_pair{|k,v| v=v.to_i} | ||
27 | - paginate_options[:page]=1 if !paginate_options.keys.include?(:page) | ||
28 | - | ||
29 | - search_result = find_by_contents(asset, context, scope, query, paginate_options, options) | 27 | + search_result = find_by_contents(asset, context, scope, query, {:page => 1}, options) |
30 | 28 | ||
31 | articles = search_result[:results] | 29 | articles = search_result[:results] |
32 | 30 | ||
33 | - result = present_articles(articles) | ||
34 | - | ||
35 | - result | 31 | + present_articles(articles) |
36 | end | 32 | end |
37 | end | 33 | end |
38 | end | 34 | end |
lib/noosfero/api/v1/tasks.rb
@@ -20,13 +20,13 @@ module Noosfero | @@ -20,13 +20,13 @@ module Noosfero | ||
20 | get do | 20 | get do |
21 | tasks = select_filtered_collection_of(environment, 'tasks', params) | 21 | tasks = select_filtered_collection_of(environment, 'tasks', params) |
22 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)} | 22 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)} |
23 | - present tasks, :with => Entities::Task, :fields => params[:fields] | 23 | + present_partial tasks, :with => Entities::Task |
24 | end | 24 | end |
25 | 25 | ||
26 | desc "Return the task id" | 26 | desc "Return the task id" |
27 | get ':id' do | 27 | get ':id' do |
28 | task = find_task(environment, params[:id]) | 28 | task = find_task(environment, params[:id]) |
29 | - present task, :with => Entities::Task, :fields => params[:fields] | 29 | + present_partial task, :with => Entities::Task |
30 | end | 30 | end |
31 | end | 31 | end |
32 | 32 |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +require_relative 'test_helper' | ||
2 | + | ||
3 | +class ActivitiesTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + login_api | ||
7 | + end | ||
8 | + | ||
9 | + should 'get activity from profile' do | ||
10 | + person = fast_create(Person) | ||
11 | + organization = fast_create(Organization) | ||
12 | + assert_difference 'organization.activities_count' do | ||
13 | + ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization | ||
14 | + organization.reload | ||
15 | + end | ||
16 | + get "/api/v1/profiles/#{organization.id}/activities?#{params.to_query}" | ||
17 | + json = JSON.parse(last_response.body) | ||
18 | + assert 1, json["activities"].count | ||
19 | + assert_equal organization.activities.map(&:activity).first.id, json["activities"].first["id"] | ||
20 | + end | ||
21 | + | ||
22 | +end |
test/unit/api/articles_test.rb
@@ -13,6 +13,16 @@ class ArticlesTest < ActiveSupport::TestCase | @@ -13,6 +13,16 @@ class ArticlesTest < ActiveSupport::TestCase | ||
13 | assert_includes json["articles"].map { |a| a["id"] }, article.id | 13 | assert_includes json["articles"].map { |a| a["id"] }, article.id |
14 | end | 14 | end |
15 | 15 | ||
16 | + should 'get profile homepage' do | ||
17 | + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | ||
18 | + person.home_page=article | ||
19 | + person.save! | ||
20 | + | ||
21 | + get "/api/v1/profiles/#{person.id}/home_page?#{params.to_query}" | ||
22 | + json = JSON.parse(last_response.body) | ||
23 | + assert_equal article.id, json["article"]["id"] | ||
24 | + end | ||
25 | + | ||
16 | should 'not list forbidden article when listing articles' do | 26 | should 'not list forbidden article when listing articles' do |
17 | person = fast_create(Person) | 27 | person = fast_create(Person) |
18 | article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) | 28 | article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) |
@@ -74,6 +84,16 @@ class ArticlesTest < ActiveSupport::TestCase | @@ -74,6 +84,16 @@ class ArticlesTest < ActiveSupport::TestCase | ||
74 | assert_equal 1, json['total_followers'] | 84 | assert_equal 1, json['total_followers'] |
75 | end | 85 | end |
76 | 86 | ||
87 | + should 'list articles followed by me' do | ||
88 | + article1 = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | ||
89 | + fast_create(Article, :profile_id => user.person.id, :name => "Some other thing") | ||
90 | + article1.person_followers << @person | ||
91 | + get "/api/v1/articles/followed_by_me?#{params.to_query}" | ||
92 | + json = JSON.parse(last_response.body) | ||
93 | + assert_equal [article1.id], json['articles'].map { |a| a['id'] } | ||
94 | + end | ||
95 | + | ||
96 | + | ||
77 | should 'list article children' do | 97 | should 'list article children' do |
78 | article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | 98 | article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") |
79 | child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing") | 99 | child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing") |
@@ -148,6 +168,33 @@ class ArticlesTest < ActiveSupport::TestCase | @@ -148,6 +168,33 @@ class ArticlesTest < ActiveSupport::TestCase | ||
148 | end | 168 | end |
149 | end | 169 | end |
150 | 170 | ||
171 | + should 'not perform a vote twice in same article' do | ||
172 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | ||
173 | + @params[:value] = 1 | ||
174 | + ## Perform a vote twice in API should compute only one vote | ||
175 | + post "/api/v1/articles/#{article.id}/vote?#{params.to_query}" | ||
176 | + post "/api/v1/articles/#{article.id}/vote?#{params.to_query}" | ||
177 | + | ||
178 | + total = article.votes_total | ||
179 | + | ||
180 | + assert_equal 1, total | ||
181 | + end | ||
182 | + | ||
183 | + should 'not perform a vote in favor and against a proposal' do | ||
184 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | ||
185 | + @params[:value] = 1 | ||
186 | + ## Perform a vote in favor a proposal | ||
187 | + post "/api/v1/articles/#{article.id}/vote?#{params.to_query}" | ||
188 | + json = JSON.parse(last_response.body) | ||
189 | + assert_equal 201, last_response.status | ||
190 | + ## Perform a vote against a proposal | ||
191 | + @params[:value] = -1 | ||
192 | + post "/api/v1/articles/#{article.id}/vote?#{params.to_query}" | ||
193 | + json = JSON.parse(last_response.body) | ||
194 | + ## The api should not allow to save this vote | ||
195 | + assert_equal 400, last_response.status | ||
196 | + end | ||
197 | + | ||
151 | should "update body of article created by me" do | 198 | should "update body of article created by me" do |
152 | new_value = "Another body" | 199 | new_value = "Another body" |
153 | params[:article] = {:body => new_value} | 200 | params[:article] = {:body => new_value} |
@@ -606,4 +653,15 @@ class ArticlesTest < ActiveSupport::TestCase | @@ -606,4 +653,15 @@ class ArticlesTest < ActiveSupport::TestCase | ||
606 | assert_equal json['articles'].count, 2 | 653 | assert_equal json['articles'].count, 2 |
607 | end | 654 | end |
608 | 655 | ||
656 | + ARTICLE_ATTRIBUTES = %w(votes_count comments_count) | ||
657 | + | ||
658 | + ARTICLE_ATTRIBUTES.map do |attribute| | ||
659 | + | ||
660 | + define_method "test_should_expose_#{attribute}_attribute_in_article_enpoints" do | ||
661 | + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | ||
662 | + get "/api/v1/articles/#{article.id}?#{params.to_query}" | ||
663 | + json = JSON.parse(last_response.body) | ||
664 | + assert_not_nil json['article'][attribute] | ||
665 | + end | ||
666 | + end | ||
609 | end | 667 | end |
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +require_relative 'test_helper' | ||
2 | + | ||
3 | +class BoxesTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + login_api | ||
7 | + end | ||
8 | + | ||
9 | + kinds= %w[Profile Community Person Enterprise] | ||
10 | + kinds.each do |kind| | ||
11 | + should "get_boxes_from_#{kind.downcase.pluralize}" do | ||
12 | + profile_obj = fast_create(kind.constantize) | ||
13 | + box = fast_create(Box, :owner_id => profile_obj.id, :owner_type => "Profile") | ||
14 | + get "/api/v1/#{kind.downcase.pluralize}/#{profile_obj.id}/boxes?#{params.to_query}" | ||
15 | + json = JSON.parse(last_response.body) | ||
16 | + assert_equal box.id, json["boxes"].first["id"] | ||
17 | + end | ||
18 | + end | ||
19 | + | ||
20 | +end |
test/unit/api/helpers_test.rb
@@ -25,6 +25,15 @@ class APIHelpersTest < ActiveSupport::TestCase | @@ -25,6 +25,15 @@ class APIHelpersTest < ActiveSupport::TestCase | ||
25 | assert_equal user, current_user | 25 | assert_equal user, current_user |
26 | end | 26 | end |
27 | 27 | ||
28 | + should 'get the current user even with expired token' do | ||
29 | + user = create_user('someuser') | ||
30 | + user.generate_private_token! | ||
31 | + user.private_token_generated_at = DateTime.now.prev_year | ||
32 | + user.save | ||
33 | + self.params = {:private_token => user.private_token} | ||
34 | + assert_equal user, current_user | ||
35 | + end | ||
36 | + | ||
28 | should 'get the person of current user' do | 37 | should 'get the person of current user' do |
29 | user = create_user('someuser') | 38 | user = create_user('someuser') |
30 | user.generate_private_token! | 39 | user.generate_private_token! |
@@ -192,6 +201,26 @@ class APIHelpersTest < ActiveSupport::TestCase | @@ -192,6 +201,26 @@ class APIHelpersTest < ActiveSupport::TestCase | ||
192 | filter_disabled_plugins_endpoints | 201 | filter_disabled_plugins_endpoints |
193 | end | 202 | end |
194 | 203 | ||
204 | + should 'not touch in options when no fields parameter is passed' do | ||
205 | + model = mock | ||
206 | + expects(:present).with(model, {}) | ||
207 | + present_partial(model, {}) | ||
208 | + end | ||
209 | + | ||
210 | + should 'fallback to array when fields parameter is not a json when calling present partial' do | ||
211 | + model = mock | ||
212 | + params[:fields] = 'name' | ||
213 | + expects(:present).with(model, {:only => ['name']}) | ||
214 | + present_partial(model, {}) | ||
215 | + end | ||
216 | + | ||
217 | + should 'accept json as fields parameter when calling present partial' do | ||
218 | + model = mock | ||
219 | + params[:fields] = {only: [:name, {user: [:login]}]}.to_json | ||
220 | + expects(:present).with(model, {:only => ['name', {'user' => ['login']}]}) | ||
221 | + present_partial(model, {}) | ||
222 | + end | ||
223 | + | ||
195 | protected | 224 | protected |
196 | 225 | ||
197 | def error!(info, status) | 226 | def error!(info, status) |
test/unit/api/people_test.rb
@@ -15,6 +15,19 @@ class PeopleTest < ActiveSupport::TestCase | @@ -15,6 +15,19 @@ class PeopleTest < ActiveSupport::TestCase | ||
15 | assert_equivalent [person1.id, person2.id, person.id], json['people'].map {|c| c['id']} | 15 | assert_equivalent [person1.id, person2.id, person.id], json['people'].map {|c| c['id']} |
16 | end | 16 | end |
17 | 17 | ||
18 | + should 'list all members of a community' do | ||
19 | + person1 = fast_create(Person) | ||
20 | + person2 = fast_create(Person) | ||
21 | + community = fast_create(Community) | ||
22 | + community.add_member(person1) | ||
23 | + community.add_member(person2) | ||
24 | + | ||
25 | + get "/api/v1/profiles/#{community.id}/members?#{params.to_query}" | ||
26 | + json = JSON.parse(last_response.body) | ||
27 | + assert_equal 2, json["people"].count | ||
28 | + assert_equivalent [person1.id,person2.id], json["people"].map{|p| p["id"]} | ||
29 | + end | ||
30 | + | ||
18 | should 'not list invisible people' do | 31 | should 'not list invisible people' do |
19 | invisible_person = fast_create(Person, :visible => false) | 32 | invisible_person = fast_create(Person, :visible => false) |
20 | 33 | ||
@@ -47,12 +60,34 @@ class PeopleTest < ActiveSupport::TestCase | @@ -47,12 +60,34 @@ class PeopleTest < ActiveSupport::TestCase | ||
47 | assert_equal some_person.id, json['person']['id'] | 60 | assert_equal some_person.id, json['person']['id'] |
48 | end | 61 | end |
49 | 62 | ||
63 | + should 'people endpoint filter by fields parameter' do | ||
64 | + get "/api/v1/people?#{params.to_query}&fields=name" | ||
65 | + json = JSON.parse(last_response.body) | ||
66 | + expected = {'people' => [{'name' => person.name}]} | ||
67 | + assert_equal expected, json | ||
68 | + end | ||
69 | + | ||
70 | + should 'people endpoint filter by fields parameter with hierarchy' do | ||
71 | + fields = {only: [:name, {user: [:login]}]}.to_json | ||
72 | + get "/api/v1/people?#{params.to_query}&fields=#{fields}" | ||
73 | + json = JSON.parse(last_response.body) | ||
74 | + expected = {'people' => [{'name' => person.name, 'user' => {'login' => 'testapi'}}]} | ||
75 | + assert_equal expected, json | ||
76 | + end | ||
77 | + | ||
50 | should 'get logged person' do | 78 | should 'get logged person' do |
51 | get "/api/v1/people/me?#{params.to_query}" | 79 | get "/api/v1/people/me?#{params.to_query}" |
52 | json = JSON.parse(last_response.body) | 80 | json = JSON.parse(last_response.body) |
53 | assert_equal person.id, json['person']['id'] | 81 | assert_equal person.id, json['person']['id'] |
54 | end | 82 | end |
55 | 83 | ||
84 | + should 'me endpoint filter by fields parameter' do | ||
85 | + get "/api/v1/people/me?#{params.to_query}&fields=name" | ||
86 | + json = JSON.parse(last_response.body) | ||
87 | + expected = {'person' => {'name' => person.name}} | ||
88 | + assert_equal expected, json | ||
89 | + end | ||
90 | + | ||
56 | should 'not get invisible person' do | 91 | should 'not get invisible person' do |
57 | person = fast_create(Person, :visible => false) | 92 | person = fast_create(Person, :visible => false) |
58 | 93 | ||
@@ -205,4 +240,19 @@ class PeopleTest < ActiveSupport::TestCase | @@ -205,4 +240,19 @@ class PeopleTest < ActiveSupport::TestCase | ||
205 | assert_equal "www.blog.org", json['person']['additional_data']['Custom Blog'] | 240 | assert_equal "www.blog.org", json['person']['additional_data']['Custom Blog'] |
206 | end | 241 | end |
207 | 242 | ||
243 | + PERSON_ATTRIBUTES = %w(vote_count comments_count articles_count) | ||
244 | + | ||
245 | + PERSON_ATTRIBUTES.map do |attribute| | ||
246 | + define_method "test_should_not_expose_#{attribute}_attribute_in_person_enpoint_if_field_parameter_does_not_contain_the_attribute" do | ||
247 | + get "/api/v1/people/me?#{params.to_query}&fields=name" | ||
248 | + json = JSON.parse(last_response.body) | ||
249 | + assert_nil json['person'][attribute] | ||
250 | + end | ||
251 | + | ||
252 | + define_method "test_should_expose_#{attribute}_attribute_in_person_enpoints_if_field_parameter_is_passed" do | ||
253 | + get "/api/v1/people/me?#{params.to_query}&fields=#{attribute}" | ||
254 | + json = JSON.parse(last_response.body) | ||
255 | + assert_not_nil json['person'][attribute] | ||
256 | + end | ||
257 | + end | ||
208 | end | 258 | end |
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +require_relative 'test_helper' | ||
2 | + | ||
3 | +class ProfilesTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + Profile.delete_all | ||
7 | + login_api | ||
8 | + end | ||
9 | + | ||
10 | + should 'list all profiles' do | ||
11 | + person1 = fast_create(Person) | ||
12 | + person2 = fast_create(Person) | ||
13 | + community = fast_create(Community) | ||
14 | + get "/api/v1/profiles?#{params.to_query}" | ||
15 | + json = JSON.parse(last_response.body) | ||
16 | + assert_equivalent [person.id, person1.id, person2.id, community.id], json.map {|p| p['id']} | ||
17 | + end | ||
18 | + | ||
19 | + should 'get person from profile id' do | ||
20 | + some_person = fast_create(Person) | ||
21 | + get "/api/v1/profiles/#{some_person.id}?#{params.to_query}" | ||
22 | + json = JSON.parse(last_response.body) | ||
23 | + assert_equal some_person.id, json['id'] | ||
24 | + end | ||
25 | + | ||
26 | + should 'get community from profile id' do | ||
27 | + community = fast_create(Community) | ||
28 | + get "/api/v1/profiles/#{community.id}?#{params.to_query}" | ||
29 | + json = JSON.parse(last_response.body) | ||
30 | + assert_equal community.id, json['id'] | ||
31 | + end | ||
32 | +end |
test/unit/api/search_test.rb
@@ -23,6 +23,16 @@ class SearchTest < ActiveSupport::TestCase | @@ -23,6 +23,16 @@ class SearchTest < ActiveSupport::TestCase | ||
23 | assert_not_empty json['articles'] | 23 | assert_not_empty json['articles'] |
24 | end | 24 | end |
25 | 25 | ||
26 | + should 'list only articles that has children' do | ||
27 | + article = fast_create(Article, :profile_id => person.id) | ||
28 | + parent = create(Article, :profile_id => person.id, :name => 'parent article') | ||
29 | + child = create(Article, :profile_id => person.id, :parent_id => parent.id, :name => 'child article') | ||
30 | + | ||
31 | + get "/api/v1/search/article?has_children=true" | ||
32 | + json = JSON.parse(last_response.body) | ||
33 | + assert_equal parent.id, json['articles'].first['id'] | ||
34 | + end | ||
35 | + | ||
26 | should 'invalid search string articles' do | 36 | should 'invalid search string articles' do |
27 | fast_create(Article, :profile_id => person.id, :name => 'some article') | 37 | fast_create(Article, :profile_id => person.id, :name => 'some article') |
28 | get "/api/v1/search/article?query=test" | 38 | get "/api/v1/search/article?query=test" |
test/unit/api/session_test.rb
@@ -182,4 +182,14 @@ class SessionTest < ActiveSupport::TestCase | @@ -182,4 +182,14 @@ class SessionTest < ActiveSupport::TestCase | ||
182 | assert_equal 404, last_response.status | 182 | assert_equal 404, last_response.status |
183 | end | 183 | end |
184 | 184 | ||
185 | + should 'not return private token when the registered user is inactive' do | ||
186 | + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" } | ||
187 | + post "/api/v1/register?#{params.to_query}" | ||
188 | + assert_equal 201, last_response.status | ||
189 | + json = JSON.parse(last_response.body) | ||
190 | + assert !User['newuserapi'].activated? | ||
191 | + assert !json['user']['activated'] | ||
192 | + assert !json['user']['private_token'].present? | ||
193 | + end | ||
194 | + | ||
185 | end | 195 | end |