Commit 42b3475d1f217d929e20e076f1fffe0b7cf12cf7

Authored by Leandro Santos
2 parents fd06f939 bd70a538

Merge branch 'master' of gitlab.com:noosfero/noosfero

app/controllers/application_controller.rb
@@ -184,13 +184,7 @@ class ApplicationController < ActionController::Base @@ -184,13 +184,7 @@ class ApplicationController < ActionController::Base
184 end 184 end
185 185
186 include SearchTermHelper 186 include SearchTermHelper
187 -  
188 - def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={})  
189 - scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?  
190 - search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options)  
191 - register_search_term(query, scope.count, search[:results].count, context, asset)  
192 - search  
193 - end 187 + include FindByContents
194 188
195 def find_suggestions(query, context, asset, options={}) 189 def find_suggestions(query, context, asset, options={})
196 plugins.dispatch_first(:find_suggestions, query, context, asset, options) 190 plugins.dispatch_first(:find_suggestions, query, context, asset, options)
config/docker/dev/Dockerfile
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # 2 #
3 # VERSION 0.0.1 3 # VERSION 0.0.1
4 4
5 -FROM debian:wheezy 5 +FROM debian:jessie
6 MAINTAINER Noosfero Development Team <noosfero-dev@listas.softwarelivre.org> 6 MAINTAINER Noosfero Development Team <noosfero-dev@listas.softwarelivre.org>
7 7
8 LABEL Description="This dockerfile builds a noosfero development environment." 8 LABEL Description="This dockerfile builds a noosfero development environment."
@@ -13,4 +13,6 @@ RUN git clone --depth 1 https://gitlab.com/noosfero/noosfero.git . @@ -13,4 +13,6 @@ RUN git clone --depth 1 https://gitlab.com/noosfero/noosfero.git .
13 13
14 RUN sh script/quick-start --skip-translations 14 RUN sh script/quick-start --skip-translations
15 15
  16 +RUN service postgresql start && sleep 2 && ruby script/sample-data
  17 +
16 EXPOSE 3000 18 EXPOSE 3000
lib/create_thumbnails_job.rb
@@ -3,5 +3,9 @@ class CreateThumbnailsJob &lt; Struct.new(:class_name, :file_id) @@ -3,5 +3,9 @@ class CreateThumbnailsJob &lt; Struct.new(:class_name, :file_id)
3 return unless class_name.constantize.exists?(file_id) 3 return unless class_name.constantize.exists?(file_id)
4 file = class_name.constantize.find(file_id) 4 file = class_name.constantize.find(file_id)
5 file.create_thumbnails 5 file.create_thumbnails
  6 + article = Article.where(:image_id => file_id).first
  7 + if article
  8 + article.touch
  9 + end
6 end 10 end
7 end 11 end
lib/find_by_contents.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +module FindByContents
  2 +
  3 + def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={})
  4 + scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?
  5 + search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options)
  6 + register_search_term(query, scope.count, search[:results].count, context, asset)
  7 + search
  8 + end
  9 +
  10 +end
  11 +
lib/noosfero/api/api.rb
1 require 'grape' 1 require 'grape'
2 #require 'rack/contrib' 2 #require 'rack/contrib'
3 -  
4 Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file unless file =~ /api\.rb/} 3 Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file unless file =~ /api\.rb/}
  4 +
5 module Noosfero 5 module Noosfero
6 module API 6 module API
7 class API < Grape::API 7 class API < Grape::API
@@ -17,7 +17,6 @@ module Noosfero @@ -17,7 +17,6 @@ module Noosfero
17 end 17 end
18 18
19 @@NOOSFERO_CONF = nil 19 @@NOOSFERO_CONF = nil
20 -  
21 def self.NOOSFERO_CONF 20 def self.NOOSFERO_CONF
22 if @@NOOSFERO_CONF 21 if @@NOOSFERO_CONF
23 @@NOOSFERO_CONF 22 @@NOOSFERO_CONF
@@ -27,9 +26,11 @@ module Noosfero @@ -27,9 +26,11 @@ module Noosfero
27 end 26 end
28 end 27 end
29 28
  29 + before { set_locale }
30 before { setup_multitenancy } 30 before { setup_multitenancy }
31 before { detect_stuff_by_domain } 31 before { detect_stuff_by_domain }
32 before { filter_disabled_plugins_endpoints } 32 before { filter_disabled_plugins_endpoints }
  33 + before { init_noosfero_plugins }
33 after { set_session_cookie } 34 after { set_session_cookie }
34 35
35 version 'v1' 36 version 'v1'
@@ -41,11 +42,17 @@ module Noosfero @@ -41,11 +42,17 @@ module Noosfero
41 42
42 mount V1::Articles 43 mount V1::Articles
43 mount V1::Comments 44 mount V1::Comments
  45 + mount V1::Users
44 mount V1::Communities 46 mount V1::Communities
45 mount V1::People 47 mount V1::People
46 mount V1::Enterprises 48 mount V1::Enterprises
47 mount V1::Categories 49 mount V1::Categories
48 mount V1::Tasks 50 mount V1::Tasks
  51 + mount V1::Tags
  52 + mount V1::Environments
  53 + mount V1::Search
  54 + mount V1::Contacts
  55 +
49 mount Session 56 mount Session
50 57
51 # hook point which allow plugins to add Grape::API extensions to API::API 58 # hook point which allow plugins to add Grape::API extensions to API::API
lib/noosfero/api/entities.rb
@@ -6,6 +6,35 @@ module Noosfero @@ -6,6 +6,35 @@ module Noosfero
6 date.strftime('%Y/%m/%d %H:%M:%S') if date 6 date.strftime('%Y/%m/%d %H:%M:%S') if date
7 end 7 end
8 8
  9 + PERMISSIONS = {
  10 + :admin => 0,
  11 + :self => 10,
  12 + :friend => 20,
  13 + :logged_user => 30,
  14 + :anonymous => 40
  15 + }
  16 +
  17 + def self.can_display? profile, options, field, permission = :friend
  18 + return true if profile.public_fields.include?(field)
  19 + current_person = options[:current_person]
  20 +
  21 + current_permission = if current_person.present?
  22 + if current_person.is_admin?
  23 + :admin
  24 + elsif current_person == profile
  25 + :self
  26 + elsif current_person.friends.include?(profile)
  27 + :friend
  28 + else
  29 + :logged_user
  30 + end
  31 + else
  32 + :anonymous
  33 + end
  34 +
  35 + PERMISSIONS[current_permission] <= PERMISSIONS[permission]
  36 + end
  37 +
9 class Image < Entity 38 class Image < Entity
10 root 'images', 'image' 39 root 'images', 'image'
11 40
@@ -30,66 +59,81 @@ module Noosfero @@ -30,66 +59,81 @@ module Noosfero
30 end 59 end
31 end 60 end
32 61
  62 + class CategoryBase < Entity
  63 + root 'categories', 'category'
  64 + expose :name, :id, :slug
  65 + end
  66 +
  67 + class Category < CategoryBase
  68 + root 'categories', 'category'
  69 + expose :full_name do |category, options|
  70 + category.full_name
  71 + end
  72 + expose :parent, :using => CategoryBase, if: { parent: true }
  73 + expose :children, :using => CategoryBase, if: { children: true }
  74 + expose :image, :using => Image
  75 + expose :display_color
  76 + end
  77 +
  78 + class Region < Category
  79 + root 'regions', 'region'
  80 + expose :parent_id
  81 + end
  82 +
33 class Profile < Entity 83 class Profile < Entity
34 expose :identifier, :name, :id 84 expose :identifier, :name, :id
35 expose :created_at, :format_with => :timestamp 85 expose :created_at, :format_with => :timestamp
36 expose :updated_at, :format_with => :timestamp 86 expose :updated_at, :format_with => :timestamp
37 expose :image, :using => Image 87 expose :image, :using => Image
  88 + expose :region, :using => Region
38 end 89 end
39 90
40 - class User < Entity 91 + class UserBasic < Entity
41 expose :id 92 expose :id
42 expose :login 93 expose :login
43 end 94 end
44 95
45 class Person < Profile 96 class Person < Profile
46 root 'people', 'person' 97 root 'people', 'person'
47 - expose :user, :using => User 98 + expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' }
48 end 99 end
  100 +
49 class Enterprise < Profile 101 class Enterprise < Profile
50 root 'enterprises', 'enterprise' 102 root 'enterprises', 'enterprise'
51 end 103 end
  104 +
52 class Community < Profile 105 class Community < Profile
53 root 'communities', 'community' 106 root 'communities', 'community'
54 expose :description 107 expose :description
55 - expose :categories  
56 - expose :members, :using => Person  
57 - end  
58 -  
59 - class CategoryBase < Entity  
60 - root 'categories', 'category'  
61 - expose :name, :id  
62 - end  
63 -  
64 - class Category < CategoryBase  
65 - root 'categories', 'category'  
66 - expose :slug  
67 - expose :full_name do |category, options|  
68 - category.full_name 108 + expose :admins do |community, options|
  109 + community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id}}
69 end 110 end
70 - expose :parent, :using => CategoryBase, if: { parent: true }  
71 - expose :children, :using => CategoryBase, if: { children: true }  
72 - expose :image, :using => Image 111 + expose :categories, :using => Category
  112 + expose :members, :using => Person
73 end 113 end
74 114
75 class ArticleBase < Entity 115 class ArticleBase < Entity
76 root 'articles', 'article' 116 root 'articles', 'article'
77 expose :id 117 expose :id
78 expose :body 118 expose :body
79 - expose :abstract 119 + expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'}
80 expose :created_at, :format_with => :timestamp 120 expose :created_at, :format_with => :timestamp
81 expose :updated_at, :format_with => :timestamp 121 expose :updated_at, :format_with => :timestamp
82 expose :title, :documentation => {:type => "String", :desc => "Title of the article"} 122 expose :title, :documentation => {:type => "String", :desc => "Title of the article"}
83 - expose :created_by, :as => :author, :using => Profile  
84 - expose :profile, :using => Profile 123 + expose :created_by, :as => :author, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile author that create the article'}
  124 + expose :profile, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile associated with the article'}
85 expose :categories, :using => Category 125 expose :categories, :using => Category
86 expose :image, :using => Image 126 expose :image, :using => Image
87 - #TODO Apply vote stuff in core and make this test  
88 expose :votes_for 127 expose :votes_for
89 expose :votes_against 128 expose :votes_against
90 expose :setting 129 expose :setting
91 expose :position 130 expose :position
92 expose :hits 131 expose :hits
  132 + expose :start_date
  133 + expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'}
  134 + expose :tag_list
  135 + expose :children_count
  136 + expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"}
93 expose :path 137 expose :path
94 end 138 end
95 139
@@ -106,8 +150,32 @@ module Noosfero @@ -106,8 +150,32 @@ module Noosfero
106 expose :author, :using => Profile 150 expose :author, :using => Profile
107 end 151 end
108 152
  153 + class User < Entity
  154 + root 'users', 'user'
  155 +
  156 + attrs = [:id,:login,:email,:activated?]
  157 + aliases = {:activated? => :activated}
  158 +
  159 + attrs.each do |attribute|
  160 + name = aliases.has_key?(attribute) ? aliases[attribute] : attribute
  161 + expose attribute, :as => name, :if => lambda{|user,options| Entities.can_display?(user.person, options, attribute)}
  162 + end
  163 +
  164 + expose :person, :using => Person
  165 + expose :permissions, :if => lambda{|user,options| Entities.can_display?(user.person, options, :permissions, :self)} do |user, options|
  166 + output = {}
  167 + user.person.role_assignments.map do |role_assigment|
  168 + if role_assigment.resource.respond_to?(:identifier) && !role_assigment.role.nil?
  169 + output[role_assigment.resource.identifier] = role_assigment.role.permissions
  170 + end
  171 + end
  172 + output
  173 + end
  174 + end
  175 +
109 class UserLogin < User 176 class UserLogin < User
110 - expose :private_token 177 + root 'users', 'user'
  178 + expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}
111 end 179 end
112 180
113 class Task < Entity 181 class Task < Entity
@@ -116,6 +184,16 @@ module Noosfero @@ -116,6 +184,16 @@ module Noosfero
116 expose :type 184 expose :type
117 end 185 end
118 186
  187 + class Environment < Entity
  188 + expose :name
  189 + end
  190 +
  191 + class Tag < Entity
  192 + root 'tags', 'tag'
  193 + expose :name
  194 + end
  195 +
  196 +
119 end 197 end
120 end 198 end
121 end 199 end
lib/noosfero/api/helpers.rb
1 -module Noosfero  
2 - module API  
3 - module APIHelpers 1 +require 'grape'
  2 +require_relative '../../find_by_contents'
  3 +
  4 + module Noosfero;
  5 + module API
  6 + module APIHelpers
4 PRIVATE_TOKEN_PARAM = :private_token 7 PRIVATE_TOKEN_PARAM = :private_token
5 - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type] 8 + DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id]
  9 +
  10 + include SanitizeParams
  11 + include Noosfero::Plugin::HotSpot
  12 + include ForgotPasswordHelper
  13 + include SearchTermHelper
  14 +
  15 + def set_locale
  16 + I18n.locale = (params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
  17 + end
  18 +
  19 + def init_noosfero_plugins
  20 + plugins
  21 + end
6 22
7 def current_user 23 def current_user
8 private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s 24 private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s
@@ -23,6 +39,22 @@ module Noosfero @@ -23,6 +39,22 @@ module Noosfero
23 @environment 39 @environment
24 end 40 end
25 41
  42 + include FindByContents
  43 +
  44 + ####################################################################
  45 + #### SEARCH
  46 + ####################################################################
  47 + def multiple_search?(searches=nil)
  48 + ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1)
  49 + end
  50 + ####################################################################
  51 +
  52 + def logger
  53 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
  54 + logger.formatter = GrapeLogging::Formatters::Default.new
  55 + logger
  56 + end
  57 +
26 def limit 58 def limit
27 limit = params[:limit].to_i 59 limit = params[:limit].to_i
28 limit = default_limit if limit <= 0 60 limit = default_limit if limit <= 0
@@ -50,7 +82,7 @@ module Noosfero @@ -50,7 +82,7 @@ module Noosfero
50 82
51 def find_article(articles, id) 83 def find_article(articles, id)
52 article = articles.find(id) 84 article = articles.find(id)
53 - article.display_to?(current_user.person) ? article : forbidden! 85 + article.display_to?(current_person) ? article : forbidden!
54 end 86 end
55 87
56 def post_article(asset, params) 88 def post_article(asset, params)
@@ -75,12 +107,25 @@ module Noosfero @@ -75,12 +107,25 @@ module Noosfero
75 present article, :with => Entities::Article, :fields => params[:fields] 107 present article, :with => Entities::Article, :fields => params[:fields]
76 end 108 end
77 109
78 - def present_articles(asset)  
79 - articles = select_filtered_collection_of(asset, 'articles', params)  
80 - articles = articles.display_filter(current_person, nil) 110 + def present_articles_for_asset(asset, method = 'articles')
  111 + articles = find_articles(asset, method)
  112 + present_articles(articles)
  113 + end
  114 +
  115 + def present_articles(articles)
81 present articles, :with => Entities::Article, :fields => params[:fields] 116 present articles, :with => Entities::Article, :fields => params[:fields]
82 end 117 end
83 118
  119 + def find_articles(asset, method = 'articles')
  120 + articles = select_filtered_collection_of(asset, method, params)
  121 + if current_person.present?
  122 + articles = articles.display_filter(current_person, nil)
  123 + else
  124 + articles = articles.published
  125 + end
  126 + articles
  127 + end
  128 +
84 def find_task(asset, id) 129 def find_task(asset, id)
85 task = asset.tasks.find(id) 130 task = asset.tasks.find(id)
86 current_person.has_permission?(task.permission, asset) ? task : forbidden! 131 current_person.has_permission?(task.permission, asset) ? task : forbidden!
@@ -127,8 +172,27 @@ module Noosfero @@ -127,8 +172,27 @@ module Noosfero
127 conditions 172 conditions
128 end 173 end
129 174
130 - def make_order_with_parameters(params)  
131 - params[:order] || "created_at DESC" 175 + # changing make_order_with_parameters to avoid sql injection
  176 + def make_order_with_parameters(object, method, params)
  177 + order = "created_at DESC"
  178 + unless params[:order].blank?
  179 + if params[:order].include? '\'' or params[:order].include? '"'
  180 + order = "created_at DESC"
  181 + elsif ['RANDOM()', 'RANDOM'].include? params[:order].upcase
  182 + order = 'RANDOM()'
  183 + else
  184 + field_name, direction = params[:order].split(' ')
  185 + assoc = object.class.reflect_on_association(method.to_sym)
  186 + if !field_name.blank? and assoc
  187 + if assoc.klass.attribute_names.include? field_name
  188 + if direction.present? and ['ASC','DESC'].include? direction.upcase
  189 + order = "#{field_name} #{direction.upcase}"
  190 + end
  191 + end
  192 + end
  193 + end
  194 + end
  195 + return order
132 end 196 end
133 197
134 def make_page_number_with_parameters(params) 198 def make_page_number_with_parameters(params)
@@ -152,25 +216,36 @@ module Noosfero @@ -152,25 +216,36 @@ module Noosfero
152 end 216 end
153 217
154 def by_reference(scope, params) 218 def by_reference(scope, params)
155 - if params[:reference_id]  
156 - created_at = scope.find(params[:reference_id]).created_at  
157 - scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at) 219 + reference_id = params[:reference_id].to_i == 0 ? nil : params[:reference_id].to_i
  220 + if reference_id.nil?
  221 + scope
158 else 222 else
  223 + created_at = scope.find(reference_id).created_at
  224 + scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at)
  225 + end
  226 + end
  227 +
  228 + def by_categories(scope, params)
  229 + category_ids = params[:category_ids]
  230 + if category_ids.nil?
159 scope 231 scope
  232 + else
  233 + scope.joins(:categories).where(:categories => {:id => category_ids})
160 end 234 end
161 end 235 end
162 236
163 def select_filtered_collection_of(object, method, params) 237 def select_filtered_collection_of(object, method, params)
164 conditions = make_conditions_with_parameter(params) 238 conditions = make_conditions_with_parameter(params)
165 - order = make_order_with_parameters(params) 239 + order = make_order_with_parameters(object,method,params)
166 page_number = make_page_number_with_parameters(params) 240 page_number = make_page_number_with_parameters(params)
167 per_page = make_per_page_with_parameters(params) 241 per_page = make_per_page_with_parameters(params)
168 timestamp = make_timestamp_with_parameters_and_method(params, method) 242 timestamp = make_timestamp_with_parameters_and_method(params, method)
169 243
170 objects = object.send(method) 244 objects = object.send(method)
171 objects = by_reference(objects, params) 245 objects = by_reference(objects, params)
  246 + objects = by_categories(objects, params)
172 247
173 - objects = objects.where(conditions).where(timestamp).page(page_number).per_page(per_page).order(order) 248 + objects = objects.where(conditions).where(timestamp).page(page_number).per_page(per_page).reorder(order)
174 249
175 objects 250 objects
176 end 251 end
@@ -179,6 +254,7 @@ module Noosfero @@ -179,6 +254,7 @@ module Noosfero
179 unauthorized! unless current_user 254 unauthorized! unless current_user
180 end 255 end
181 256
  257 +
182 # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash 258 # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash
183 # or a Bad Request error is invoked. 259 # or a Bad Request error is invoked.
184 # 260 #
@@ -198,20 +274,6 @@ module Noosfero @@ -198,20 +274,6 @@ module Noosfero
198 attrs 274 attrs
199 end 275 end
200 276
201 - def verify_recaptcha_v2(remote_ip, g_recaptcha_response, private_key, api_recaptcha_verify_uri)  
202 - verify_hash = {  
203 - "secret" => private_key,  
204 - "remoteip" => remote_ip,  
205 - "response" => g_recaptcha_response  
206 - }  
207 - uri = URI(api_recaptcha_verify_uri)  
208 - https = Net::HTTP.new(uri.host, uri.port)  
209 - https.use_ssl = true  
210 - request = Net::HTTP::Post.new(uri.path)  
211 - request.set_form_data(verify_hash)  
212 - JSON.parse(https.request(request).body)  
213 - end  
214 -  
215 ########################################## 277 ##########################################
216 # error helpers # 278 # error helpers #
217 ########################################## 279 ##########################################
@@ -247,13 +309,22 @@ module Noosfero @@ -247,13 +309,22 @@ module Noosfero
247 render_api_error!(_('Method Not Allowed'), 405) 309 render_api_error!(_('Method Not Allowed'), 405)
248 end 310 end
249 311
250 - def render_api_error!(message, status)  
251 - error!({'message' => message, :code => status}, status) 312 + # javascript_console_message is supposed to be executed as console.log()
  313 + def render_api_error!(user_message, status, log_message = nil, javascript_console_message = nil)
  314 + message_hash = {'message' => user_message, :code => status}
  315 + message_hash[:javascript_console_message] = javascript_console_message if javascript_console_message.present?
  316 + log_msg = "#{status}, User message: #{user_message}"
  317 + log_msg = "#{log_message}, #{log_msg}" if log_message.present?
  318 + log_msg = "#{log_msg}, Javascript Console Message: #{javascript_console_message}" if javascript_console_message.present?
  319 + logger.error log_msg unless Rails.env.test?
  320 + error!(message_hash, status)
252 end 321 end
253 322
254 def render_api_errors!(messages) 323 def render_api_errors!(messages)
  324 + messages = messages.to_a if messages.class == ActiveModel::Errors
255 render_api_error!(messages.join(','), 400) 325 render_api_error!(messages.join(','), 400)
256 end 326 end
  327 +
257 protected 328 protected
258 329
259 def set_session_cookie 330 def set_session_cookie
@@ -278,7 +349,7 @@ module Noosfero @@ -278,7 +349,7 @@ module Noosfero
278 end 349 end
279 350
280 def filter_disabled_plugins_endpoints 351 def filter_disabled_plugins_endpoints
281 - not_found! if Noosfero::API::API.endpoint_unavailable?(self, !@environment) 352 + not_found! if Noosfero::API::API.endpoint_unavailable?(self, @environment)
282 end 353 end
283 354
284 private 355 private
@@ -305,7 +376,6 @@ module Noosfero @@ -305,7 +376,6 @@ module Noosfero
305 def period(from_date, until_date) 376 def period(from_date, until_date)
306 begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date 377 begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date
307 end_period = until_date.nil? ? DateTime.now : until_date 378 end_period = until_date.nil? ? DateTime.now : until_date
308 -  
309 begin_period..end_period 379 begin_period..end_period
310 end 380 end
311 381
lib/noosfero/api/session.rb
@@ -2,7 +2,6 @@ require &quot;uri&quot; @@ -2,7 +2,6 @@ require &quot;uri&quot;
2 2
3 module Noosfero 3 module Noosfero
4 module API 4 module API
5 -  
6 class Session < Grape::API 5 class Session < Grape::API
7 6
8 # Login to get token 7 # Login to get token
@@ -14,11 +13,15 @@ module Noosfero @@ -14,11 +13,15 @@ module Noosfero
14 # Example Request: 13 # Example Request:
15 # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin 14 # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin
16 post "/login" do 15 post "/login" do
17 - user ||= User.authenticate(params[:login], params[:password], environment) 16 + begin
  17 + user ||= User.authenticate(params[:login], params[:password], environment)
  18 + rescue NoosferoExceptions::UserNotActivated => e
  19 + render_api_error!(e.message, 401)
  20 + end
18 21
19 return unauthorized! unless user 22 return unauthorized! unless user
20 @current_user = user 23 @current_user = user
21 - present user, :with => Entities::UserLogin 24 + present user, :with => Entities::UserLogin, :current_person => current_person
22 end 25 end
23 26
24 # Create user. 27 # Create user.
@@ -28,34 +31,103 @@ module Noosfero @@ -28,34 +31,103 @@ module Noosfero
28 # password (required) - Password 31 # password (required) - Password
29 # login - login 32 # login - login
30 # Example Request: 33 # Example Request:
31 - # POST /register?email=some@mail.com&password=pas&login=some 34 + # POST /register?email=some@mail.com&password=pas&password_confirmation=pas&login=some
32 params do 35 params do
33 requires :email, type: String, desc: _("Email") 36 requires :email, type: String, desc: _("Email")
34 requires :login, type: String, desc: _("Login") 37 requires :login, type: String, desc: _("Login")
35 requires :password, type: String, desc: _("Password") 38 requires :password, type: String, desc: _("Password")
36 end 39 end
  40 +
37 post "/register" do 41 post "/register" do
38 - unique_attributes! User, [:email, :login]  
39 - attrs = attributes_for_keys [:email, :login, :password]  
40 - attrs[:password_confirmation] = attrs[:password]  
41 -  
42 - #Commented for stress tests  
43 -  
44 - # remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])  
45 - # private_key = API.NOOSFERO_CONF['api_recaptcha_private_key']  
46 - # api_recaptcha_verify_uri = API.NOOSFERO_CONF['api_recaptcha_verify_uri']  
47 - # captcha_result = verify_recaptcha_v2(remote_ip, params['g-recaptcha-response'], private_key, api_recaptcha_verify_uri)  
48 - user = User.new(attrs)  
49 -# if captcha_result["success"] and user.save  
50 - if user.save  
51 - user.activate  
52 - user.generate_private_token!  
53 - present user, :with => Entities::UserLogin  
54 - else  
55 - message = user.errors.to_json 42 + attrs = attributes_for_keys [:email, :login, :password, :password_confirmation] + environment.signup_person_fields
  43 + name = params[:name].present? ? params[:name] : attrs[:email]
  44 + attrs[:password_confirmation] = attrs[:password] if !attrs.has_key?(:password_confirmation)
  45 + user = User.new(attrs.merge(:name => name))
  46 +
  47 + begin
  48 + user.signup!
  49 + user.generate_private_token! if user.activated?
  50 + present user, :with => Entities::UserLogin, :current_person => user.person
  51 + rescue ActiveRecord::RecordInvalid
  52 + message = user.errors.as_json.merge((user.person.present? ? user.person.errors : {}).as_json).to_json
56 render_api_error!(message, 400) 53 render_api_error!(message, 400)
57 end 54 end
58 end 55 end
  56 +
  57 + params do
  58 + requires :activation_code, type: String, desc: _("Activation token")
  59 + end
  60 +
  61 + # Activate a user.
  62 + #
  63 + # Parameter:
  64 + # activation_code (required) - Activation token
  65 + # Example Request:
  66 + # PATCH /activate?activation_code=28259abd12cc6a64ef9399cf3286cb998b96aeaf
  67 + patch "/activate" do
  68 + user = User.find_by_activation_code(params[:activation_code])
  69 + if user
  70 + unless user.environment.enabled?('admin_must_approve_new_users')
  71 + if user.activate
  72 + user.generate_private_token!
  73 + present user, :with => Entities::UserLogin, :current_person => current_person
  74 + end
  75 + else
  76 + if user.create_moderate_task
  77 + user.activation_code = nil
  78 + user.save!
  79 +
  80 + # Waiting for admin moderate user registration
  81 + status 202
  82 + body({
  83 + :message => 'Waiting for admin moderate user registration'
  84 + })
  85 + end
  86 + end
  87 + else
  88 + # Token not found in database
  89 + render_api_error!(_('Token is invalid'), 412)
  90 + end
  91 + end
  92 +
  93 + # Request a new password.
  94 + #
  95 + # Parameters:
  96 + # value (required) - Email or login
  97 + # Example Request:
  98 + # POST /forgot_password?value=some@mail.com
  99 + post "/forgot_password" do
  100 + requestors = fetch_requestors(params[:value])
  101 + not_found! if requestors.blank?
  102 + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
  103 + requestors.each do |requestor|
  104 + ChangePassword.create!(:requestor => requestor)
  105 + end
  106 + end
  107 +
  108 + params do
  109 + requires :code, type: String, desc: _("Forgot password code")
  110 + end
  111 + # Change password
  112 + #
  113 + # Parameters:
  114 + # code (required) - Change password code
  115 + # password (required)
  116 + # password_confirmation (required)
  117 + # Example Request:
  118 + # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret
  119 + patch "/new_password" do
  120 + change_password = ChangePassword.find_by_code(params[:code])
  121 + not_found! if change_password.nil?
  122 +
  123 + if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation])
  124 + change_password.finish
  125 + present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person
  126 + else
  127 + something_wrong!
  128 + end
  129 + end
  130 +
59 end 131 end
60 end 132 end
61 end 133 end
lib/noosfero/api/v1/articles.rb
@@ -2,7 +2,6 @@ module Noosfero @@ -2,7 +2,6 @@ module Noosfero
2 module API 2 module API
3 module V1 3 module V1
4 class Articles < Grape::API 4 class Articles < Grape::API
5 - before { authenticate! }  
6 5
7 ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} 6 ARTICLE_TYPES = Article.descendants.map{|a| a.to_s}
8 7
@@ -17,39 +16,148 @@ module Noosfero @@ -17,39 +16,148 @@ module Noosfero
17 # 16 #
18 # Example Request: 17 # Example Request:
19 # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 18 # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317
  19 +
  20 + desc 'Return all articles of all kinds' do
  21 + detail 'Get all articles filtered by fields in query params'
  22 + params Noosfero::API::Entities::Article.documentation
  23 + success Noosfero::API::Entities::Article
  24 + failure [[403, 'Forbidden']]
  25 + named 'ArticlesList'
  26 + headers [
  27 + 'Per-Page' => {
  28 + description: 'Total number of records',
  29 + required: false
  30 + }
  31 + ]
  32 + end
20 get do 33 get do
21 - present_articles(environment) 34 + present_articles_for_asset(environment)
22 end 35 end
23 36
24 - desc "Return the article id"  
25 - get ':id' do 37 + desc "Return one article by id" do
  38 + detail 'Get only one article by id. If not found the "forbidden" http error is showed'
  39 + params Noosfero::API::Entities::Article.documentation
  40 + success Noosfero::API::Entities::Article
  41 + failure [[403, 'Forbidden']]
  42 + named 'ArticleById'
  43 + end
  44 + get ':id', requirements: {id: /[0-9]+/} do
26 present_article(environment) 45 present_article(environment)
27 end 46 end
28 47
  48 + post ':id' do
  49 + article = environment.articles.find(params[:id])
  50 + return forbidden! unless article.allow_edit?(current_person)
  51 + article.update_attributes!(params[:article])
  52 + present article, :with => Entities::Article, :fields => params[:fields]
  53 + end
  54 +
  55 + desc 'Report a abuse and/or violent content in a article by id' do
  56 + detail 'Submit a abuse (in general, a content violation) report about a specific article'
  57 + params Noosfero::API::Entities::Article.documentation
  58 + failure [[400, 'Bad Request']]
  59 + named 'ArticleReportAbuse'
  60 + end
  61 + post ':id/report_abuse' do
  62 + article = find_article(environment.articles, params[:id])
  63 + profile = article.profile
  64 + begin
  65 + abuse_report = AbuseReport.new(:reason => params[:report_abuse])
  66 + if !params[:content_type].blank?
  67 + article = params[:content_type].constantize.find(params[:content_id])
  68 + abuse_report.content = article_reported_version(article)
  69 + end
  70 +
  71 + current_person.register_report(abuse_report, profile)
  72 +
  73 + if !params[:content_type].blank?
  74 + abuse_report = AbuseReport.find_by_reporter_id_and_abuse_complaint_id(current_person.id, profile.opened_abuse_complaint.id)
  75 + Delayed::Job.enqueue DownloadReportedImagesJob.new(abuse_report, article)
  76 + end
  77 +
  78 + {
  79 + :success => true,
  80 + :message => _('Your abuse report was registered. The administrators are reviewing your report.'),
  81 + }
  82 + rescue Exception => exception
  83 + #logger.error(exception.to_s)
  84 + render_api_error!(_('Your report couldn\'t be saved due to some problem. Please contact the administrator.'), 400)
  85 + end
  86 +
  87 + end
  88 +
  89 + desc "Returns the articles I voted" do
  90 + detail 'Get the Articles I make a vote'
  91 + failure [[403, 'Forbidden']]
  92 + named 'ArticleFollowers'
  93 + end
  94 + #FIXME refactor this method
  95 + get 'voted_by_me' do
  96 + present_articles(current_person.votes.collect(&:voteable))
  97 + end
  98 +
  99 + desc 'Perform a vote on a article by id' do
  100 + detail 'Vote on a specific article with values: 1 (if you like) or -1 (if not)'
  101 + params Noosfero::API::Entities::UserLogin.documentation
  102 + failure [[401,'Unauthorized']]
  103 + named 'ArticleVote'
  104 + end
  105 + post ':id/vote' do
  106 + authenticate!
  107 + value = (params[:value] || 1).to_i
  108 + # FIXME verify allowed values
  109 + render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value)
  110 + article = find_article(environment.articles, params[:id])
  111 + vote = Vote.new(:voteable => article, :voter => current_person, :vote => value)
  112 + {:vote => vote.save}
  113 + end
  114 +
  115 + desc 'Return the children of a article identified by id' do
  116 + detail 'Get all children articles of a specific article'
  117 + params Noosfero::API::Entities::Article.documentation
  118 + failure [[403, 'Forbidden']]
  119 + named 'ArticleChildren'
  120 + end
  121 +
29 get ':id/children' do 122 get ':id/children' do
30 article = find_article(environment.articles, params[:id]) 123 article = find_article(environment.articles, params[:id])
31 124
32 #TODO make tests for this situation 125 #TODO make tests for this situation
33 votes_order = params.delete(:order) if params[:order]=='votes_score' 126 votes_order = params.delete(:order) if params[:order]=='votes_score'
34 articles = select_filtered_collection_of(article, 'children', params) 127 articles = select_filtered_collection_of(article, 'children', params)
35 - articles = articles.display_filter(current_person, nil)  
36 - 128 + articles = articles.display_filter(current_person, article.profile)
37 129
38 #TODO make tests for this situation 130 #TODO make tests for this situation
39 if votes_order 131 if votes_order
40 articles = articles.joins('left join votes on articles.id=votes.voteable_id').group('articles.id').reorder('sum(coalesce(votes.vote, 0)) DESC') 132 articles = articles.joins('left join votes on articles.id=votes.voteable_id').group('articles.id').reorder('sum(coalesce(votes.vote, 0)) DESC')
41 end 133 end
42 -  
43 Article.hit(articles) 134 Article.hit(articles)
44 - present articles, :with => Entities::Article, :fields => params[:fields] 135 + present_articles(articles)
45 end 136 end
46 137
  138 + desc 'Return one child of a article identified by id' do
  139 + detail 'Get a child of a specific article'
  140 + params Noosfero::API::Entities::Article.documentation
  141 + success Noosfero::API::Entities::Article
  142 + failure [[403, 'Forbidden']]
  143 + named 'ArticleChild'
  144 + end
47 get ':id/children/:child_id' do 145 get ':id/children/:child_id' do
48 article = find_article(environment.articles, params[:id]) 146 article = find_article(environment.articles, params[:id])
49 - present find_article(article.children, params[:child_id]), :with => Entities::Article, :fields => params[:fields] 147 + child = find_article(article.children, params[:child_id])
  148 + child.hit
  149 + present child, :with => Entities::Article, :fields => params[:fields]
50 end 150 end
51 151
  152 + desc 'Suggest a article to another profile' do
  153 + detail 'Suggest a article to another profile (person, community...)'
  154 + params Noosfero::API::Entities::Article.documentation
  155 + success Noosfero::API::Entities::Task
  156 + failure [[401,'Unauthorized']]
  157 + named 'ArticleSuggest'
  158 + end
52 post ':id/children/suggest' do 159 post ':id/children/suggest' do
  160 + authenticate!
53 parent_article = environment.articles.find(params[:id]) 161 parent_article = environment.articles.find(params[:id])
54 162
55 suggest_article = SuggestArticle.new 163 suggest_article = SuggestArticle.new
@@ -66,8 +174,15 @@ module Noosfero @@ -66,8 +174,15 @@ module Noosfero
66 174
67 # Example Request: 175 # Example Request:
68 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body 176 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body
  177 + desc 'Add a child article to a parent identified by id' do
  178 + detail 'Create a new article and associate to a parent'
  179 + params Noosfero::API::Entities::Article.documentation
  180 + success Noosfero::API::Entities::Article
  181 + failure [[401,'Unauthorized']]
  182 + named 'ArticleAddChild'
  183 + end
69 post ':id/children' do 184 post ':id/children' do
70 - 185 + authenticate!
71 parent_article = environment.articles.find(params[:id]) 186 parent_article = environment.articles.find(params[:id])
72 return forbidden! unless parent_article.allow_create?(current_person) 187 return forbidden! unless parent_article.allow_create?(current_person)
73 188
@@ -95,11 +210,37 @@ module Noosfero @@ -95,11 +210,37 @@ module Noosfero
95 resource kind.pluralize.to_sym do 210 resource kind.pluralize.to_sym do
96 segment "/:#{kind}_id" do 211 segment "/:#{kind}_id" do
97 resource :articles do 212 resource :articles do
  213 +
  214 + desc "Return all articles associate with a profile of type #{kind}" do
  215 + detail 'Get a list of articles of a profile'
  216 + params Noosfero::API::Entities::Article.documentation
  217 + success Noosfero::API::Entities::Article
  218 + failure [[403, 'Forbidden']]
  219 + named 'ArticlesOfProfile'
  220 + end
98 get do 221 get do
99 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 222 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
100 - present_articles(profile) 223 +
  224 + if params[:path].present?
  225 + article = profile.articles.find_by_path(params[:path])
  226 + if !article || !article.display_to?(current_person)
  227 + article = forbidden!
  228 + end
  229 +
  230 + present article, :with => Entities::Article, :fields => params[:fields]
  231 + else
  232 +
  233 + present_articles_for_asset(profile)
  234 + end
101 end 235 end
102 236
  237 + desc "Return a article associate with a profile of type #{kind}" do
  238 + detail 'Get only one article of a profile'
  239 + params Noosfero::API::Entities::Article.documentation
  240 + success Noosfero::API::Entities::Article
  241 + failure [[403, 'Forbidden']]
  242 + named 'ArticleOfProfile'
  243 + end
103 get ':id' do 244 get ':id' do
104 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 245 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
105 present_article(profile) 246 present_article(profile)
@@ -107,6 +248,13 @@ module Noosfero @@ -107,6 +248,13 @@ module Noosfero
107 248
108 # Example Request: 249 # Example Request:
109 # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body 250 # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body
  251 + desc "Add a new article associated with a profile of type #{kind}" do
  252 + detail 'Create a new article and associate with a profile'
  253 + params Noosfero::API::Entities::Article.documentation
  254 + success Noosfero::API::Entities::Article
  255 + failure [[403, 'Forbidden']]
  256 + named 'ArticleCreateToProfile'
  257 + end
110 post do 258 post do
111 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 259 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
112 post_article(profile, params) 260 post_article(profile, params)
lib/noosfero/api/v1/comments.rb
@@ -30,8 +30,8 @@ module Noosfero @@ -30,8 +30,8 @@ module Noosfero
30 # POST api/v1/articles/12/comments?private_token=2298743290432&body=new comment&title=New 30 # POST api/v1/articles/12/comments?private_token=2298743290432&body=new comment&title=New
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)  
34 - present article.comments.create(options), :with => Entities::Comment 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
35 end 35 end
36 end 36 end
37 37
lib/noosfero/api/v1/contacts.rb 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Contacts < Grape::API
  5 +
  6 + resource :communities do
  7 +
  8 + resource ':id/contact' do
  9 + #contact => {:name => 'some name', :email => 'test@mail.com', :subject => 'some title', :message => 'some message'}
  10 + desc "Send a contact message"
  11 + post do
  12 + profile = environment.communities.find(params[:id])
  13 + forbidden! unless profile.present?
  14 + contact = Contact.new params[:contact].merge(dest: profile)
  15 + if contact.deliver
  16 + {:success => true}
  17 + else
  18 + {:success => false}
  19 + end
  20 + end
  21 +
  22 + end
  23 + end
  24 +
  25 + end
  26 + end
  27 + end
  28 +end
lib/noosfero/api/v1/environments.rb 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Environments < Grape::API
  5 +
  6 + resource :environment do
  7 +
  8 + desc "Return the person information"
  9 + get '/signup_person_fields' do
  10 + present environment.signup_person_fields
  11 + end
  12 +
  13 + end
  14 +
  15 + end
  16 + end
  17 + end
  18 +end
lib/noosfero/api/v1/people.rb
@@ -48,6 +48,13 @@ module Noosfero @@ -48,6 +48,13 @@ module Noosfero
48 present person, :with => Entities::Person 48 present person, :with => Entities::Person
49 end 49 end
50 50
  51 + desc "Update person information"
  52 + post ':id' do
  53 + return forbidden! if current_person.id.to_s != params[:id]
  54 + current_person.update_attributes!(params[:person])
  55 + present current_person, :with => Entities::Person
  56 + end
  57 +
51 # Example Request: 58 # Example Request:
52 # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack 59 # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack
53 desc "Create person" 60 desc "Create person"
lib/noosfero/api/v1/search.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Search < Grape::API
  5 +
  6 + resource :search do
  7 + resource :article do
  8 + get do
  9 + # Security checks
  10 + sanitize_params_hash(params)
  11 + # APIHelpers
  12 + asset = :articles
  13 + context = environment
  14 +
  15 + 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 = 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.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present?
  20 + query = params[:query] || ""
  21 + order = "more_recent"
  22 +
  23 + options = {:filter => order, :template_id => params[:template_id]}
  24 +
  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)
  30 +
  31 + articles = search_result[:results]
  32 +
  33 + result = present_articles(articles)
  34 +
  35 + result
  36 + end
  37 + end
  38 + end
  39 +
  40 + end
  41 + end
  42 + end
  43 +end
lib/noosfero/api/v1/tags.rb 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Tags < Grape::API
  5 + before { authenticate! }
  6 +
  7 + resource :articles do
  8 +
  9 + resource ':id/tags' do
  10 +
  11 + get do
  12 + article = find_article(environment.articles, params[:id])
  13 + present article.tag_list
  14 + end
  15 +
  16 + desc "Add a tag to an article"
  17 + post do
  18 + article = find_article(environment.articles, params[:id])
  19 + article.tag_list=params[:tags]
  20 + article.save
  21 + present article.tag_list
  22 + end
  23 +
  24 + end
  25 + end
  26 +
  27 + end
  28 + end
  29 + end
  30 +end
lib/noosfero/api/v1/users.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Users < Grape::API
  5 + before { authenticate! }
  6 +
  7 + resource :users do
  8 +
  9 + get do
  10 + users = select_filtered_collection_of(environment, 'users', params)
  11 + users = users.select{|u| u.person.display_info_to? current_person}
  12 + present users, :with => Entities::User, :current_person => current_person
  13 + end
  14 +
  15 + get "/me" do
  16 + present current_user, :with => Entities::User, :current_person => current_person
  17 + end
  18 +
  19 + get ":id" do
  20 + user = environment.users.find_by_id(params[:id])
  21 + unless user.person.display_info_to? current_person
  22 + unauthorized!
  23 + end
  24 + present user, :with => Entities::User, :current_person => current_person
  25 + end
  26 +
  27 + get ":id/permissions" do
  28 + user = environment.users.find(params[:id])
  29 + output = {}
  30 + user.person.role_assignments.map do |role_assigment|
  31 + if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile]
  32 + output[:permissions] = role_assigment.role.permissions
  33 + end
  34 + end
  35 + present output
  36 + end
  37 +
  38 + end
  39 +
  40 + end
  41 + end
  42 + end
  43 +end
lib/sanitize_params.rb 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +module SanitizeParams
  2 +
  3 + protected
  4 +
  5 + # Check each request parameter for
  6 + # improper HTML or Script tags
  7 + def sanitize_params
  8 + sanitize_params_hash(request.params)
  9 + end
  10 +
  11 + # Given a params list sanitize all
  12 + def sanitize_params_hash(params)
  13 + params.each { |k, v|
  14 + if v.is_a?(String)
  15 + params[k] = sanitize_param v
  16 + elsif v.is_a?(Array)
  17 + params[k] = sanitize_array v
  18 + elsif v.kind_of?(Hash)
  19 + params[k] = sanitize_params_hash(v)
  20 + end
  21 + }
  22 + end
  23 +
  24 + # If the parameter was an array,
  25 + # try to sanitize each element in the array
  26 + def sanitize_array(array)
  27 + array.map! { |e|
  28 + if e.is_a?(String)
  29 + sanitize_param e
  30 + end
  31 + }
  32 + return array
  33 + end
  34 +
  35 + # Santitize a single value
  36 + def sanitize_param(value)
  37 + allowed_tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p)
  38 + ActionController::Base.helpers.sanitize(value, tags: allowed_tags, attributes: %w(href title))
  39 + end
  40 +
  41 +end
plugins/newsletter/db/migrate/20150717195546_newsletter_plugin_newsletters.rb
@@ -14,7 +14,7 @@ class NewsletterPluginNewsletters &lt; ActiveRecord::Migration @@ -14,7 +14,7 @@ class NewsletterPluginNewsletters &lt; ActiveRecord::Migration
14 t.boolean :moderated 14 t.boolean :moderated
15 t.text :unsubscribers 15 t.text :unsubscribers
16 end 16 end
17 - add_index :newsletter_plugin_newsletters, :environment_id, :uniq => true 17 + add_index :newsletter_plugin_newsletters, :environment_id, :unique => true
18 end 18 end
19 19
20 def down 20 def down
plugins/newsletter/lib/newsletter_plugin/newsletter.rb
1 require 'csv' 1 require 'csv'
2 2
3 -class NewsletterPlugin::Newsletter < Noosfero::Plugin::ActiveRecord 3 +class NewsletterPlugin::Newsletter < ActiveRecord::Base
4 4
5 belongs_to :environment 5 belongs_to :environment
6 belongs_to :person 6 belongs_to :person
@@ -123,11 +123,11 @@ class NewsletterPlugin::Newsletter &lt; Noosfero::Plugin::ActiveRecord @@ -123,11 +123,11 @@ class NewsletterPlugin::Newsletter &lt; Noosfero::Plugin::ActiveRecord
123 end 123 end
124 124
125 def post_with_image(post) 125 def post_with_image(post)
126 - content_tag(:tr,content_tag(:td,tag(:img, :src => "#{self.environment.top_url}#{post.image.public_filename(:big)}", :id => post.id),:style => CSS['post-image'])+content_tag(:td,content_tag(:span, show_date(post.published_at), :style => CSS['post-date'])+content_tag(:h3, link_to(h(post.title), post.url, :style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(190)),:style => CSS['post-lead'])+read_more(post.url), :style => CSS['post-info'])) 126 + content_tag(:tr,content_tag(:td,tag(:img, :src => "#{self.environment.top_url}#{post.image.public_filename(:big)}", :id => post.id),:style => CSS['post-image'])+content_tag(:td,content_tag(:span, show_date(post.published_at), :style => CSS['post-date'])+content_tag(:h3, link_to(h(post.title), post.url, :style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(190), tags: %w(strong em b i)),:style => CSS['post-lead'])+read_more(post.url), :style => CSS['post-info']))
127 end 127 end
128 128
129 def post_without_image(post) 129 def post_without_image(post)
130 - content_tag(:tr, content_tag(:td,content_tag(:span, show_date(post.published_at),:style => CSS['post-date'], :id => post.id)+content_tag(:h3, link_to(h(post.title), post.url,:style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(360)),:style => CSS['post-lead'])+read_more(post.url),:colspan => 2, :style => CSS['post-info'])) 130 + content_tag(:tr, content_tag(:td,content_tag(:span, show_date(post.published_at),:style => CSS['post-date'], :id => post.id)+content_tag(:h3, link_to(h(post.title), post.url,:style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(360), tags: %w(strong em b i)),:style => CSS['post-lead'])+read_more(post.url),:colspan => 2, :style => CSS['post-info']))
131 end 131 end
132 132
133 def body(data = {}) 133 def body(data = {})
@@ -177,10 +177,6 @@ class NewsletterPlugin::Newsletter &lt; Noosfero::Plugin::ActiveRecord @@ -177,10 +177,6 @@ class NewsletterPlugin::Newsletter &lt; Noosfero::Plugin::ActiveRecord
177 last_mailing.nil? ? nil : last_mailing.created_at 177 last_mailing.nil? ? nil : last_mailing.created_at
178 end 178 end
179 179
180 - def sanitize(html)  
181 - html.gsub(/<\/?p>/, '')  
182 - end  
183 -  
184 def has_posts_in_the_period? 180 def has_posts_in_the_period?
185 ! self.posts.empty? 181 ! self.posts.empty?
186 end 182 end
plugins/newsletter/public/style.css
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 } 14 }
15 15
16 #newsletter-moderation-preview { 16 #newsletter-moderation-preview {
17 - margin-left: 25px; 17 + margin-left: 10px;
18 } 18 }
19 19
20 #newsletter-moderation-preview input[type=checkbox] { 20 #newsletter-moderation-preview input[type=checkbox] {
plugins/newsletter/test/unit/newsletter_plugin_newsletter_test.rb
@@ -351,15 +351,30 @@ EOS @@ -351,15 +351,30 @@ EOS
351 post = fast_create(TextArticle, :parent_id => blog.id, 351 post = fast_create(TextArticle, :parent_id => blog.id,
352 :name => 'the last news 1', 352 :name => 'the last news 1',
353 :profile_id => community.id, 353 :profile_id => community.id,
354 - :body => "<p>paragraph of news</p>") 354 + :body => '<p style="text-align: left;">paragraph of news</p>')
355 355
356 newsletter = NewsletterPlugin::Newsletter.create!( 356 newsletter = NewsletterPlugin::Newsletter.create!(
357 :environment => environment, 357 :environment => environment,
358 :blog_ids => [blog.id], 358 :blog_ids => [blog.id],
359 :person => fast_create(Person)) 359 :person => fast_create(Person))
360 360
361 - assert_match /<p>paragraph of news<\/p>/, post.body  
362 - assert_not_match /<p>paragraph of news<\/p>/, newsletter.body 361 + assert_match /<p style="text-align: left;">paragraph of news<\/p>/, post.body
  362 + assert_not_match /<p style="text-align: left;">paragraph of news<\/p>/, newsletter.body
  363 + end
  364 +
  365 + should 'only include text for posts in HTML generated content' do
  366 + environment = fast_create Environment
  367 + community = fast_create(Community, :environment_id => environment.id)
  368 + blog = fast_create(Blog, :profile_id => community.id)
  369 + post = fast_create(TextArticle, :profile_id => community.id, :parent_id => blog.id, :name => 'the last news', :abstract => 'A picture<img src="example.png"> is <em>worth</em> a thousand words. <hr><h1>The main goals of visualization</h1>')
  370 + newsletter = NewsletterPlugin::Newsletter.create!(
  371 + :environment => environment,
  372 + :blog_ids => [blog.id],
  373 + :person => fast_create(Person))
  374 +
  375 + assert_match /A picture<img src="example.png"> is <em>worth<\/em> a thousand words. <hr><h1>The main goals of visualization<\/h1>/, post.abstract
  376 + # Tags for text emphasis are whitelisted
  377 + assert_match /A picture is <em>worth<\/em> a thousand words. The main goals of visualization/, newsletter.body
363 end 378 end
364 379
365 should 'filter posts when listing posts for newsletter' do 380 should 'filter posts when listing posts for newsletter' do
plugins/shopping_cart/db/migrate/20131226125124_move_shopping_cart_purchase_order_to_orders_plugin_order.rb
1 OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item 1 OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item
2 OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order 2 OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order
3 3
4 -class ShoppingCartPlugin::PurchaseOrder < Noosfero::Plugin::ActiveRecord 4 +class ShoppingCartPlugin::PurchaseOrder < ActiveRecord::Base
5 acts_as_having_settings :field => :data 5 acts_as_having_settings :field => :data
6 6
7 module Status 7 module Status
@@ -16,10 +16,10 @@ class Profile @@ -16,10 +16,10 @@ class Profile
16 has_many :orders, :class_name => 'OrdersPlugin::Order' 16 has_many :orders, :class_name => 'OrdersPlugin::Order'
17 end 17 end
18 18
19 -class OrdersPlugin::Item < Noosfero::Plugin::ActiveRecord 19 +class OrdersPlugin::Item < ActiveRecord::Base
20 belongs_to :order, :class_name => 'OrdersPlugin::Order' 20 belongs_to :order, :class_name => 'OrdersPlugin::Order'
21 end 21 end
22 -class OrdersPlugin::Order < Noosfero::Plugin::ActiveRecord 22 +class OrdersPlugin::Order < ActiveRecord::Base
23 has_many :items, :class_name => 'OrdersPlugin::Item', :foreign_key => :order_id 23 has_many :items, :class_name => 'OrdersPlugin::Item', :foreign_key => :order_id
24 24
25 extend CodeNumbering::ClassMethods 25 extend CodeNumbering::ClassMethods
script/quick-start
@@ -133,6 +133,9 @@ if [ ! -f .gitignore ]; then @@ -133,6 +133,9 @@ if [ ! -f .gitignore ]; then
133 ln -s gitignore.example .gitignore 133 ln -s gitignore.example .gitignore
134 fi 134 fi
135 135
  136 +# remove obsolete symbolic link added by old versions
  137 +rm -f vendor/rails
  138 +
136 # you can now start the server 139 # you can now start the server
137 say "I: Congratulations, you are ready to run Noosfero." 140 say "I: Congratulations, you are ready to run Noosfero."
138 say "I: To execute Noosfero in development mode, run \`./script/development\` and browse to http://localhost:3000" 141 say "I: To execute Noosfero in development mode, run \`./script/development\` and browse to http://localhost:3000"
test/unit/api/articles_test.rb
@@ -31,7 +31,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -31,7 +31,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
31 end 31 end
32 32
33 should 'not return article if user has no permission to view it' do 33 should 'not return article if user has no permission to view it' do
34 - person = fast_create(Person) 34 + person = fast_create(Person, :environment_id => environment.id)
35 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) 35 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
36 assert !article.published? 36 assert !article.published?
37 37
@@ -48,8 +48,17 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -48,8 +48,17 @@ class ArticlesTest &lt; ActiveSupport::TestCase
48 assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] } 48 assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] }
49 end 49 end
50 50
  51 + should 'list public article children for not logged in access' do
  52 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  53 + child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing")
  54 + child2 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing")
  55 + get "/api/v1/articles/#{article.id}/children"
  56 + json = JSON.parse(last_response.body)
  57 + assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] }
  58 + end
  59 +
51 should 'not list children of forbidden article' do 60 should 'not list children of forbidden article' do
52 - person = fast_create(Person) 61 + person = fast_create(Person, :environment_id => environment.id)
53 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) 62 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
54 child1 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing") 63 child1 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
55 child2 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing") 64 child2 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
@@ -58,7 +67,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -58,7 +67,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
58 end 67 end
59 68
60 should 'not return child of forbidden article' do 69 should 'not return child of forbidden article' do
61 - person = fast_create(Person) 70 + person = fast_create(Person, :environment_id => environment.id)
62 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false) 71 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
63 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing") 72 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
64 get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}" 73 get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}"
@@ -66,7 +75,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -66,7 +75,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
66 end 75 end
67 76
68 should 'not return private child' do 77 should 'not return private child' do
69 - person = fast_create(Person) 78 + person = fast_create(Person, :environment_id => environment.id)
70 article = fast_create(Article, :profile_id => person.id, :name => "Some thing") 79 article = fast_create(Article, :profile_id => person.id, :name => "Some thing")
71 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false) 80 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false)
72 get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}" 81 get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}"
@@ -74,7 +83,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -74,7 +83,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
74 end 83 end
75 84
76 should 'not list private child' do 85 should 'not list private child' do
77 - person = fast_create(Person) 86 + person = fast_create(Person, :environment_id => environment.id)
78 article = fast_create(Article, :profile_id => person.id, :name => "Some thing") 87 article = fast_create(Article, :profile_id => person.id, :name => "Some thing")
79 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false) 88 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false)
80 get "/api/v1/articles/#{article.id}/children?#{params.to_query}" 89 get "/api/v1/articles/#{article.id}/children?#{params.to_query}"
@@ -82,6 +91,74 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -82,6 +91,74 @@ class ArticlesTest &lt; ActiveSupport::TestCase
82 assert_not_includes json['articles'].map {|a| a['id']}, child.id 91 assert_not_includes json['articles'].map {|a| a['id']}, child.id
83 end 92 end
84 93
  94 + should 'perform a vote in a article identified by id' do
  95 + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing")
  96 + @params[:value] = 1
  97 +
  98 + post "/api/v1/articles/#{article.id}/vote?#{params.to_query}"
  99 + json = JSON.parse(last_response.body)
  100 +
  101 + assert_not_equal 401, last_response.status
  102 + assert_equal true, json['vote']
  103 + end
  104 +
  105 + expose_attributes = %w(id body abstract created_at title author profile categories image votes_for votes_against setting position hits start_date end_date tag_list parent children children_count)
  106 +
  107 + expose_attributes.each do |attr|
  108 + should "expose article #{attr} attribute by default" do
  109 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  110 + get "/api/v1/articles/?#{params.to_query}"
  111 + json = JSON.parse(last_response.body)
  112 + assert json["articles"].last.has_key?(attr)
  113 + end
  114 + end
  115 +
  116 + should "update body of article created by me" do
  117 + new_value = "Another body"
  118 + params[:article] = {:body => new_value}
  119 + article = fast_create(Article, :profile_id => person.id)
  120 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  121 + json = JSON.parse(last_response.body)
  122 + assert_equal new_value, json["article"]["body"]
  123 + end
  124 +
  125 + should "update title of article created by me" do
  126 + new_value = "Another name"
  127 + params[:article] = {:name => new_value}
  128 + article = fast_create(Article, :profile_id => person.id)
  129 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  130 + json = JSON.parse(last_response.body)
  131 + assert_equal new_value, json["article"]["title"]
  132 + end
  133 +
  134 + should 'not update article of another user' do
  135 + another_person = fast_create(Person, :environment_id => environment.id)
  136 + article = fast_create(Article, :profile_id => another_person.id)
  137 + params[:article] = {:title => 'Some title'}
  138 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  139 + assert_equal 403, last_response.status
  140 + end
  141 +
  142 + should 'not update article without permission in community' do
  143 + community = fast_create(Community, :environment_id => environment.id)
  144 + article = fast_create(Article, :profile_id => community.id)
  145 + params[:article] = {:name => 'New title'}
  146 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  147 + assert_equal 403, last_response.status
  148 + end
  149 +
  150 +
  151 + should 'update article of community if user has permission' do
  152 + community = fast_create(Community, :environment_id => environment.id)
  153 + give_permission(person, 'post_content', community)
  154 + article = fast_create(Article, :profile_id => community.id)
  155 + new_value = "Another body"
  156 + params[:article] = {:body => new_value}
  157 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  158 + json = JSON.parse(last_response.body)
  159 + assert_equal new_value, json["article"]["body"]
  160 + end
  161 +
85 should 'list articles with pagination' do 162 should 'list articles with pagination' do
86 Article.destroy_all 163 Article.destroy_all
87 article_one = fast_create(Article, :profile_id => user.person.id, :name => "Another thing", :created_at => 2.days.ago) 164 article_one = fast_create(Article, :profile_id => user.person.id, :name => "Another thing", :created_at => 2.days.ago)
@@ -126,7 +203,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -126,7 +203,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
126 profile_kinds = %w(community person enterprise) 203 profile_kinds = %w(community person enterprise)
127 profile_kinds.each do |kind| 204 profile_kinds.each do |kind|
128 should "return article by #{kind}" do 205 should "return article by #{kind}" do
129 - profile = fast_create(kind.camelcase.constantize) 206 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
130 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing") 207 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing")
131 get "/api/v1/#{kind.pluralize}/#{profile.id}/articles/#{article.id}?#{params.to_query}" 208 get "/api/v1/#{kind.pluralize}/#{profile.id}/articles/#{article.id}?#{params.to_query}"
132 json = JSON.parse(last_response.body) 209 json = JSON.parse(last_response.body)
@@ -134,7 +211,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -134,7 +211,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
134 end 211 end
135 212
136 should "not return article by #{kind} if user has no permission to view it" do 213 should "not return article by #{kind} if user has no permission to view it" do
137 - profile = fast_create(kind.camelcase.constantize) 214 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
138 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false) 215 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false)
139 assert !article.published? 216 assert !article.published?
140 217
@@ -143,7 +220,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -143,7 +220,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
143 end 220 end
144 221
145 should "not list forbidden article when listing articles by #{kind}" do 222 should "not list forbidden article when listing articles by #{kind}" do
146 - profile = fast_create(kind.camelcase.constantize) 223 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
147 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false) 224 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false)
148 assert !article.published? 225 assert !article.published?
149 226
@@ -151,6 +228,29 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -151,6 +228,29 @@ class ArticlesTest &lt; ActiveSupport::TestCase
151 json = JSON.parse(last_response.body) 228 json = JSON.parse(last_response.body)
152 assert_not_includes json['articles'].map {|a| a['id']}, article.id 229 assert_not_includes json['articles'].map {|a| a['id']}, article.id
153 end 230 end
  231 +
  232 + should "return article by #{kind} and path" do
  233 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  234 + parent_article = Folder.create!(:profile => profile, :name => "Parent Folder")
  235 + article = Article.create!(:profile => profile, :name => "Some thing", :parent => parent_article)
  236 +
  237 + params[:path] = parent_article.slug+'/'+article.slug
  238 + get "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
  239 + json = JSON.parse(last_response.body)
  240 + assert_equal article.id, json["article"]["id"]
  241 + end
  242 +
  243 + should "not return article by #{kind} and path if user has no permission to view it" do
  244 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  245 + parent_article = Folder.create!(:profile => profile, :name => "Parent Folder")
  246 + article = Article.create!(:profile => profile, :name => "Some thing", :parent => parent_article, :published => false)
  247 +
  248 + assert !article.published?
  249 +
  250 + params[:path] = parent_article.slug+'/'+article.slug
  251 + get "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
  252 + assert_equal 403, last_response.status
  253 + end
154 end 254 end
155 255
156 ############################# 256 #############################
@@ -160,7 +260,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -160,7 +260,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
160 group_kinds = %w(community enterprise) 260 group_kinds = %w(community enterprise)
161 group_kinds.each do |kind| 261 group_kinds.each do |kind|
162 should "#{kind}: create article" do 262 should "#{kind}: create article" do
163 - profile = fast_create(kind.camelcase.constantize) 263 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
164 give_permission(user.person, 'post_content', profile) 264 give_permission(user.person, 'post_content', profile)
165 params[:article] = {:name => "Title"} 265 params[:article] = {:name => "Title"}
166 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" 266 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
@@ -169,16 +269,16 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -169,16 +269,16 @@ class ArticlesTest &lt; ActiveSupport::TestCase
169 end 269 end
170 270
171 should "#{kind}: do not create article if user has no permission to post content" do 271 should "#{kind}: do not create article if user has no permission to post content" do
172 - profile = fast_create(kind.camelcase.constantize) 272 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
173 give_permission(user.person, 'invite_members', profile) 273 give_permission(user.person, 'invite_members', profile)
174 params[:article] = {:name => "Title"} 274 params[:article] = {:name => "Title"}
175 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" 275 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
176 assert_equal 403, last_response.status 276 assert_equal 403, last_response.status
177 end 277 end
178 278
179 - should "#{kind}: create article with parent" do  
180 - profile = fast_create(kind.camelcase.constantize)  
181 - profile.add_member(user.person) 279 + should "#{kind} create article with parent" do
  280 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  281 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
182 article = fast_create(Article) 282 article = fast_create(Article)
183 283
184 params[:article] = {:name => "Title", :parent_id => article.id} 284 params[:article] = {:name => "Title", :parent_id => article.id}
@@ -187,9 +287,9 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -187,9 +287,9 @@ class ArticlesTest &lt; ActiveSupport::TestCase
187 assert_equal article.id, json["article"]["parent"]["id"] 287 assert_equal article.id, json["article"]["parent"]["id"]
188 end 288 end
189 289
190 - should "#{kind}: create article with content type passed as parameter" do  
191 - profile = fast_create(kind.camelcase.constantize)  
192 - profile.add_member(user.person) 290 + should "#{kind} create article with content type passed as parameter" do
  291 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  292 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
193 293
194 Article.delete_all 294 Article.delete_all
195 params[:article] = {:name => "Title"} 295 params[:article] = {:name => "Title"}
@@ -201,8 +301,8 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -201,8 +301,8 @@ class ArticlesTest &lt; ActiveSupport::TestCase
201 end 301 end
202 302
203 should "#{kind}: create article of TinyMceArticle type if no content type is passed as parameter" do 303 should "#{kind}: create article of TinyMceArticle type if no content type is passed as parameter" do
204 - profile = fast_create(kind.camelcase.constantize)  
205 - profile.add_member(user.person) 304 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  305 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
206 306
207 params[:article] = {:name => "Title"} 307 params[:article] = {:name => "Title"}
208 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" 308 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
@@ -212,7 +312,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -212,7 +312,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
212 end 312 end
213 313
214 should "#{kind}: not create article with invalid article content type" do 314 should "#{kind}: not create article with invalid article content type" do
215 - profile = fast_create(kind.camelcase.constantize) 315 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
216 profile.add_member(user.person) 316 profile.add_member(user.person)
217 317
218 params[:article] = {:name => "Title"} 318 params[:article] = {:name => "Title"}
@@ -223,20 +323,20 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -223,20 +323,20 @@ class ArticlesTest &lt; ActiveSupport::TestCase
223 assert_equal 403, last_response.status 323 assert_equal 403, last_response.status
224 end 324 end
225 325
226 - should "#{kind}: create article defining the correct profile" do  
227 - profile = fast_create(kind.camelcase.constantize)  
228 - profile.add_member(user.person) 326 + should "#{kind} create article defining the correct profile" do
  327 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  328 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
229 329
230 params[:article] = {:name => "Title"} 330 params[:article] = {:name => "Title"}
231 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" 331 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
232 json = JSON.parse(last_response.body) 332 json = JSON.parse(last_response.body)
233 333
234 - assert_equal profile, Article.last.profile 334 + assert_equal profile.id, json['article']['profile']['id']
235 end 335 end
236 336
237 should "#{kind}: create article defining the created_by" do 337 should "#{kind}: create article defining the created_by" do
238 - profile = fast_create(kind.camelcase.constantize)  
239 - profile.add_member(user.person) 338 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  339 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
240 340
241 params[:article] = {:name => "Title"} 341 params[:article] = {:name => "Title"}
242 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" 342 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
@@ -246,8 +346,8 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -246,8 +346,8 @@ class ArticlesTest &lt; ActiveSupport::TestCase
246 end 346 end
247 347
248 should "#{kind}: create article defining the last_changed_by" do 348 should "#{kind}: create article defining the last_changed_by" do
249 - profile = fast_create(kind.camelcase.constantize)  
250 - profile.add_member(user.person) 349 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  350 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
251 351
252 params[:article] = {:name => "Title"} 352 params[:article] = {:name => "Title"}
253 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}" 353 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
@@ -269,7 +369,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -269,7 +369,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
269 end 369 end
270 370
271 should 'person do not create article if user has no permission to post content' do 371 should 'person do not create article if user has no permission to post content' do
272 - person = fast_create(Person) 372 + person = fast_create(Person, :environment_id => environment.id)
273 params[:article] = {:name => "Title"} 373 params[:article] = {:name => "Title"}
274 post "/api/v1/people/#{person.id}/articles?#{params.to_query}" 374 post "/api/v1/people/#{person.id}/articles?#{params.to_query}"
275 assert_equal 403, last_response.status 375 assert_equal 403, last_response.status
@@ -376,4 +476,99 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -376,4 +476,99 @@ class ArticlesTest &lt; ActiveSupport::TestCase
376 assert_equal [0, 1, 1], [a1.reload.hits, a2.reload.hits, a3.reload.hits] 476 assert_equal [0, 1, 1], [a1.reload.hits, a2.reload.hits, a3.reload.hits]
377 end 477 end
378 478
  479 + should 'update hit attribute of article specific children' do
  480 + a1 = fast_create(Article, :profile_id => user.person.id)
  481 + a2 = fast_create(Article, :parent_id => a1.id, :profile_id => user.person.id)
  482 + get "/api/v1/articles/#{a1.id}/children/#{a2.id}?#{params.to_query}"
  483 + json = JSON.parse(last_response.body)
  484 + assert_equal 1, json['article']['hits']
  485 + end
  486 +
  487 + should 'list all events of a community in a given category' do
  488 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  489 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  490 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  491 + e1 = fast_create(Event, :profile_id => co.id)
  492 + e2 = fast_create(Event, :profile_id => co.id)
  493 + e1.categories << c1
  494 + e2.categories << c2
  495 + e1.save!
  496 + e2.save!
  497 + params['content_type']='Event'
  498 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  499 + json = JSON.parse(last_response.body)
  500 + assert_equal json['articles'].count, 2
  501 + end
  502 +
  503 + should 'list a event of a community in a given category' do
  504 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  505 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  506 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  507 + e1 = fast_create(Event, :profile_id => co.id)
  508 + e2 = fast_create(Event, :profile_id => co.id)
  509 + e1.categories << c1
  510 + e2.categories << c2
  511 + e1.save!
  512 + e2.save!
  513 + params['category_ids[]']=c1.id
  514 + params['content_type']='Event'
  515 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  516 + json = JSON.parse(last_response.body)
  517 + #should show only one article, since the other not in the same category
  518 + assert_equal 1, json['articles'].count
  519 + assert_equal e1.id, json['articles'][0]['id']
  520 + end
  521 +
  522 + should 'not list uncategorized event of a community if a category is given' do
  523 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  524 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  525 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  526 + e1 = fast_create(Event, :profile_id => co.id)
  527 + e2 = fast_create(Event, :profile_id => co.id)
  528 + e3 = fast_create(Event, :profile_id => co.id)
  529 + e1.categories << c1
  530 + e2.categories << c2
  531 + params['category_ids[]']=c1.id
  532 + params['content_type']='Event'
  533 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  534 + json = JSON.parse(last_response.body)
  535 + assert_equal 1, json['articles'].count
  536 + assert_equal e1.id, json['articles'][0]['id']
  537 + end
  538 +
  539 + should 'list events of a community in a given 2 categories' do
  540 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  541 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  542 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  543 + e1 = fast_create(Event, :profile_id => co.id)
  544 + e2 = fast_create(Event, :profile_id => co.id)
  545 + e1.categories << c1
  546 + e2.categories << c2
  547 + e1.save!
  548 + e2.save!
  549 + params['content_type']='Event'
  550 + params['categories_ids'] = [c1.id, c2.id]
  551 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  552 + json = JSON.parse(last_response.body)
  553 + assert_equal json['articles'].count, 2
  554 + end
  555 +
  556 + should 'Show 2 events since it uses an IN operator for category instead of an OR' do
  557 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  558 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  559 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  560 + c3 = Category.create(environment: Environment.default, name: 'extra-category')
  561 + e1 = fast_create(Event, :profile_id => co.id)
  562 + e2 = fast_create(Event, :profile_id => co.id)
  563 + e1.categories << c1
  564 + e2.categories << c2
  565 + e1.save!
  566 + e2.save!
  567 + params['content_type']='Event'
  568 + params['categories_ids'] = [c1.id, c2.id, c3.id]
  569 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  570 + json = JSON.parse(last_response.body)
  571 + assert_equal json['articles'].count, 2
  572 + end
  573 +
379 end 574 end
test/unit/api/categories_test.rb
@@ -7,25 +7,25 @@ class CategoriesTest &lt; ActiveSupport::TestCase @@ -7,25 +7,25 @@ class CategoriesTest &lt; ActiveSupport::TestCase
7 end 7 end
8 8
9 should 'list categories' do 9 should 'list categories' do
10 - category = fast_create(Category) 10 + category = fast_create(Category, :environment_id => environment.id)
11 get "/api/v1/categories/?#{params.to_query}" 11 get "/api/v1/categories/?#{params.to_query}"
12 json = JSON.parse(last_response.body) 12 json = JSON.parse(last_response.body)
13 assert_includes json["categories"].map { |c| c["name"] }, category.name 13 assert_includes json["categories"].map { |c| c["name"] }, category.name
14 end 14 end
15 15
16 should 'get category by id' do 16 should 'get category by id' do
17 - category = fast_create(Category) 17 + category = fast_create(Category, :environment_id => environment.id)
18 get "/api/v1/categories/#{category.id}/?#{params.to_query}" 18 get "/api/v1/categories/#{category.id}/?#{params.to_query}"
19 json = JSON.parse(last_response.body) 19 json = JSON.parse(last_response.body)
20 assert_equal category.name, json["category"]["name"] 20 assert_equal category.name, json["category"]["name"]
21 end 21 end
22 22
23 should 'list parent and children when get category by id' do 23 should 'list parent and children when get category by id' do
24 - parent = fast_create(Category)  
25 - child_1 = fast_create(Category)  
26 - child_2 = fast_create(Category) 24 + parent = fast_create(Category, :environment_id => environment.id)
  25 + child_1 = fast_create(Category, :environment_id => environment.id)
  26 + child_2 = fast_create(Category, :environment_id => environment.id)
27 27
28 - category = fast_create(Category) 28 + category = fast_create(Category, :environment_id => environment.id)
29 category.parent = parent 29 category.parent = parent
30 category.children << child_1 30 category.children << child_1
31 category.children << child_2 31 category.children << child_2
@@ -33,16 +33,16 @@ class CategoriesTest &lt; ActiveSupport::TestCase @@ -33,16 +33,16 @@ class CategoriesTest &lt; ActiveSupport::TestCase
33 33
34 get "/api/v1/categories/#{category.id}/?#{params.to_query}" 34 get "/api/v1/categories/#{category.id}/?#{params.to_query}"
35 json = JSON.parse(last_response.body) 35 json = JSON.parse(last_response.body)
36 - assert_equal({'id' => parent.id, 'name' => parent.name}, json['category']['parent']) 36 + assert_equal({'id' => parent.id, 'name' => parent.name, 'slug' => parent.slug}, json['category']['parent'])
37 assert_equivalent [child_1.id, child_2.id], json['category']['children'].map { |c| c['id'] } 37 assert_equivalent [child_1.id, child_2.id], json['category']['children'].map { |c| c['id'] }
38 end 38 end
39 39
40 should 'include parent in categories list if params is true' do 40 should 'include parent in categories list if params is true' do
41 - parent_1 = fast_create(Category) # parent_1 has no parent category  
42 - child_1 = fast_create(Category)  
43 - child_2 = fast_create(Category) 41 + parent_1 = fast_create(Category, :environment_id => environment.id) # parent_1 has no parent category
  42 + child_1 = fast_create(Category, :environment_id => environment.id)
  43 + child_2 = fast_create(Category, :environment_id => environment.id)
44 44
45 - parent_2 = fast_create(Category) 45 + parent_2 = fast_create(Category, :environment_id => environment.id)
46 parent_2.parent = parent_1 46 parent_2.parent = parent_1
47 parent_2.children << child_1 47 parent_2.children << child_1
48 parent_2.children << child_2 48 parent_2.children << child_2
@@ -60,10 +60,10 @@ class CategoriesTest &lt; ActiveSupport::TestCase @@ -60,10 +60,10 @@ class CategoriesTest &lt; ActiveSupport::TestCase
60 end 60 end
61 61
62 should 'include children in categories list if params is true' do 62 should 'include children in categories list if params is true' do
63 - category = fast_create(Category)  
64 - child_1 = fast_create(Category)  
65 - child_2 = fast_create(Category)  
66 - child_3 = fast_create(Category) 63 + category = fast_create(Category, :environment_id => environment.id)
  64 + child_1 = fast_create(Category, :environment_id => environment.id)
  65 + child_2 = fast_create(Category, :environment_id => environment.id)
  66 + child_3 = fast_create(Category, :environment_id => environment.id)
67 67
68 category.children << child_1 68 category.children << child_1
69 category.children << child_2 69 category.children << child_2
@@ -83,4 +83,15 @@ class CategoriesTest &lt; ActiveSupport::TestCase @@ -83,4 +83,15 @@ class CategoriesTest &lt; ActiveSupport::TestCase
83 json["categories"].map{ |c| c['children'].map{ |child| child['id'] }.sort } 83 json["categories"].map{ |c| c['children'].map{ |child| child['id'] }.sort }
84 end 84 end
85 85
  86 + expose_attributes = %w(id name full_name image display_color)
  87 +
  88 + expose_attributes.each do |attr|
  89 + should "expose category #{attr} attribute by default" do
  90 + category = fast_create(Category, :environment_id => environment.id)
  91 + get "/api/v1/categories/?#{params.to_query}"
  92 + json = JSON.parse(last_response.body)
  93 + assert json["categories"].last.has_key?(attr)
  94 + end
  95 + end
  96 +
86 end 97 end
test/unit/api/comments_test.rb
@@ -65,4 +65,17 @@ class CommentsTest &lt; ActiveSupport::TestCase @@ -65,4 +65,17 @@ class CommentsTest &lt; ActiveSupport::TestCase
65 assert_equal 201, last_response.status 65 assert_equal 201, last_response.status
66 assert_equal body, json['comment']['body'] 66 assert_equal body, json['comment']['body']
67 end 67 end
  68 +
  69 + should 'comment creation define the source' do
  70 + amount = Comment.count
  71 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  72 + body = 'My comment'
  73 + params.merge!({:body => body})
  74 +
  75 + post "/api/v1/articles/#{article.id}/comments?#{params.to_query}"
  76 + assert_equal amount + 1, Comment.count
  77 + comment = Comment.last
  78 + assert_not_nil comment.source
  79 + end
  80 +
68 end 81 end
test/unit/api/communities_test.rb
@@ -8,8 +8,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -8,8 +8,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
8 end 8 end
9 9
10 should 'list only communities' do 10 should 'list only communities' do
11 - community = fast_create(Community)  
12 - enterprise = fast_create(Enterprise) # should not list this enterprise 11 + community = fast_create(Community, :environment_id => environment.id)
  12 + enterprise = fast_create(Enterprise, :environment_id => environment.id) # should not list this enterprise
13 get "/api/v1/communities?#{params.to_query}" 13 get "/api/v1/communities?#{params.to_query}"
14 json = JSON.parse(last_response.body) 14 json = JSON.parse(last_response.body)
15 assert_not_includes json['communities'].map {|c| c['id']}, enterprise.id 15 assert_not_includes json['communities'].map {|c| c['id']}, enterprise.id
@@ -17,16 +17,16 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -17,16 +17,16 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
17 end 17 end
18 18
19 should 'list all communities' do 19 should 'list all communities' do
20 - community1 = fast_create(Community, :public_profile => true)  
21 - community2 = fast_create(Community) 20 + community1 = fast_create(Community, :environment_id => environment.id, :public_profile => true)
  21 + community2 = fast_create(Community, :environment_id => environment.id)
22 get "/api/v1/communities?#{params.to_query}" 22 get "/api/v1/communities?#{params.to_query}"
23 json = JSON.parse(last_response.body) 23 json = JSON.parse(last_response.body)
24 assert_equivalent [community1.id, community2.id], json['communities'].map {|c| c['id']} 24 assert_equivalent [community1.id, community2.id], json['communities'].map {|c| c['id']}
25 end 25 end
26 26
27 should 'not list invisible communities' do 27 should 'not list invisible communities' do
28 - community1 = fast_create(Community)  
29 - fast_create(Community, :visible => false) 28 + community1 = fast_create(Community, :environment_id => environment.id)
  29 + fast_create(Community, :environment_id => environment.id, :visible => false)
30 30
31 get "/api/v1/communities?#{params.to_query}" 31 get "/api/v1/communities?#{params.to_query}"
32 json = JSON.parse(last_response.body) 32 json = JSON.parse(last_response.body)
@@ -34,8 +34,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -34,8 +34,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
34 end 34 end
35 35
36 should 'not list private communities without permission' do 36 should 'not list private communities without permission' do
37 - community1 = fast_create(Community)  
38 - fast_create(Community, :public_profile => false) 37 + community1 = fast_create(Community, :environment_id => environment.id)
  38 + fast_create(Community, :environment_id => environment.id, :public_profile => false)
39 39
40 get "/api/v1/communities?#{params.to_query}" 40 get "/api/v1/communities?#{params.to_query}"
41 json = JSON.parse(last_response.body) 41 json = JSON.parse(last_response.body)
@@ -43,8 +43,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -43,8 +43,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
43 end 43 end
44 44
45 should 'list private community for members' do 45 should 'list private community for members' do
46 - c1 = fast_create(Community)  
47 - c2 = fast_create(Community, :public_profile => false) 46 + c1 = fast_create(Community, :environment_id => environment.id)
  47 + c2 = fast_create(Community, :environment_id => environment.id, :public_profile => false)
48 c2.add_member(person) 48 c2.add_member(person)
49 49
50 get "/api/v1/communities?#{params.to_query}" 50 get "/api/v1/communities?#{params.to_query}"
@@ -66,7 +66,7 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -66,7 +66,7 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
66 end 66 end
67 67
68 should 'get community' do 68 should 'get community' do
69 - community = fast_create(Community) 69 + community = fast_create(Community, :environment_id => environment.id)
70 70
71 get "/api/v1/communities/#{community.id}?#{params.to_query}" 71 get "/api/v1/communities/#{community.id}?#{params.to_query}"
72 json = JSON.parse(last_response.body) 72 json = JSON.parse(last_response.body)
@@ -74,7 +74,7 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -74,7 +74,7 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
74 end 74 end
75 75
76 should 'not get invisible community' do 76 should 'not get invisible community' do
77 - community = fast_create(Community, :visible => false) 77 + community = fast_create(Community, :environment_id => environment.id, :visible => false)
78 78
79 get "/api/v1/communities/#{community.id}?#{params.to_query}" 79 get "/api/v1/communities/#{community.id}?#{params.to_query}"
80 json = JSON.parse(last_response.body) 80 json = JSON.parse(last_response.body)
@@ -82,8 +82,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -82,8 +82,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
82 end 82 end
83 83
84 should 'not get private communities without permission' do 84 should 'not get private communities without permission' do
85 - community = fast_create(Community)  
86 - fast_create(Community, :public_profile => false) 85 + community = fast_create(Community, :environment_id => environment.id)
  86 + fast_create(Community, :environment_id => environment.id, :public_profile => false)
87 87
88 get "/api/v1/communities/#{community.id}?#{params.to_query}" 88 get "/api/v1/communities/#{community.id}?#{params.to_query}"
89 json = JSON.parse(last_response.body) 89 json = JSON.parse(last_response.body)
@@ -91,17 +91,18 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -91,17 +91,18 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
91 end 91 end
92 92
93 should 'get private community for members' do 93 should 'get private community for members' do
94 - community = fast_create(Community, :public_profile => false) 94 + community = fast_create(Community, :environment_id => environment.id, :public_profile => false, :visible => true)
95 community.add_member(person) 95 community.add_member(person)
96 96
  97 +
97 get "/api/v1/communities/#{community.id}?#{params.to_query}" 98 get "/api/v1/communities/#{community.id}?#{params.to_query}"
98 json = JSON.parse(last_response.body) 99 json = JSON.parse(last_response.body)
99 assert_equal community.id, json['community']['id'] 100 assert_equal community.id, json['community']['id']
100 end 101 end
101 102
102 should 'list person communities' do 103 should 'list person communities' do
103 - community = fast_create(Community)  
104 - fast_create(Community) 104 + community = fast_create(Community, :environment_id => environment.id)
  105 + fast_create(Community, :environment_id => environment.id)
105 community.add_member(person) 106 community.add_member(person)
106 107
107 get "/api/v1/people/#{person.id}/communities?#{params.to_query}" 108 get "/api/v1/people/#{person.id}/communities?#{params.to_query}"
@@ -110,8 +111,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase @@ -110,8 +111,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
110 end 111 end
111 112
112 should 'not list person communities invisible' do 113 should 'not list person communities invisible' do
113 - c1 = fast_create(Community)  
114 - c2 = fast_create(Community, :visible => false) 114 + c1 = fast_create(Community, :environment_id => environment.id)
  115 + c2 = fast_create(Community, :environment_id => environment.id, :visible => false)
115 c1.add_member(person) 116 c1.add_member(person)
116 c2.add_member(person) 117 c2.add_member(person)
117 118
test/unit/api/enterprises_test.rb
@@ -8,8 +8,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -8,8 +8,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
8 end 8 end
9 9
10 should 'list only enterprises' do 10 should 'list only enterprises' do
11 - community = fast_create(Community) # should not list this community  
12 - enterprise = fast_create(Enterprise, :public_profile => true) 11 + community = fast_create(Community, :environment_id => environment.id) # should not list this community
  12 + enterprise = fast_create(Enterprise, :environment_id => environment.id, :public_profile => true)
13 get "/api/v1/enterprises?#{params.to_query}" 13 get "/api/v1/enterprises?#{params.to_query}"
14 json = JSON.parse(last_response.body) 14 json = JSON.parse(last_response.body)
15 assert_includes json['enterprises'].map {|c| c['id']}, enterprise.id 15 assert_includes json['enterprises'].map {|c| c['id']}, enterprise.id
@@ -17,15 +17,15 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -17,15 +17,15 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
17 end 17 end
18 18
19 should 'list all enterprises' do 19 should 'list all enterprises' do
20 - enterprise1 = fast_create(Enterprise, :public_profile => true)  
21 - enterprise2 = fast_create(Enterprise) 20 + enterprise1 = fast_create(Enterprise, :environment_id => environment.id, :public_profile => true)
  21 + enterprise2 = fast_create(Enterprise, :environment_id => environment.id)
22 get "/api/v1/enterprises?#{params.to_query}" 22 get "/api/v1/enterprises?#{params.to_query}"
23 json = JSON.parse(last_response.body) 23 json = JSON.parse(last_response.body)
24 assert_equivalent [enterprise1.id, enterprise2.id], json['enterprises'].map {|c| c['id']} 24 assert_equivalent [enterprise1.id, enterprise2.id], json['enterprises'].map {|c| c['id']}
25 end 25 end
26 26
27 should 'not list invisible enterprises' do 27 should 'not list invisible enterprises' do
28 - enterprise1 = fast_create(Enterprise) 28 + enterprise1 = fast_create(Enterprise, :environment_id => environment.id)
29 fast_create(Enterprise, :visible => false) 29 fast_create(Enterprise, :visible => false)
30 30
31 get "/api/v1/enterprises?#{params.to_query}" 31 get "/api/v1/enterprises?#{params.to_query}"
@@ -34,8 +34,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -34,8 +34,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
34 end 34 end
35 35
36 should 'not list private enterprises without permission' do 36 should 'not list private enterprises without permission' do
37 - enterprise1 = fast_create(Enterprise)  
38 - fast_create(Enterprise, :public_profile => false) 37 + enterprise1 = fast_create(Enterprise, :environment_id => environment.id)
  38 + fast_create(Enterprise, :environment_id => environment.id, :public_profile => false)
39 39
40 get "/api/v1/enterprises?#{params.to_query}" 40 get "/api/v1/enterprises?#{params.to_query}"
41 json = JSON.parse(last_response.body) 41 json = JSON.parse(last_response.body)
@@ -43,8 +43,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -43,8 +43,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
43 end 43 end
44 44
45 should 'list private enterprise for members' do 45 should 'list private enterprise for members' do
46 - c1 = fast_create(Enterprise)  
47 - c2 = fast_create(Enterprise, :public_profile => false) 46 + c1 = fast_create(Enterprise, :environment_id => environment.id)
  47 + c2 = fast_create(Enterprise, :environment_id => environment.id, :public_profile => false)
48 c2.add_member(person) 48 c2.add_member(person)
49 49
50 get "/api/v1/enterprises?#{params.to_query}" 50 get "/api/v1/enterprises?#{params.to_query}"
@@ -53,7 +53,7 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -53,7 +53,7 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
53 end 53 end
54 54
55 should 'get enterprise' do 55 should 'get enterprise' do
56 - enterprise = fast_create(Enterprise) 56 + enterprise = fast_create(Enterprise, :environment_id => environment.id)
57 57
58 get "/api/v1/enterprises/#{enterprise.id}?#{params.to_query}" 58 get "/api/v1/enterprises/#{enterprise.id}?#{params.to_query}"
59 json = JSON.parse(last_response.body) 59 json = JSON.parse(last_response.body)
@@ -69,8 +69,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -69,8 +69,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
69 end 69 end
70 70
71 should 'not get private enterprises without permission' do 71 should 'not get private enterprises without permission' do
72 - enterprise = fast_create(Enterprise)  
73 - fast_create(Enterprise, :public_profile => false) 72 + enterprise = fast_create(Enterprise, :environment_id => environment.id)
  73 + fast_create(Enterprise, :environment_id => environment.id, :public_profile => false)
74 74
75 get "/api/v1/enterprises/#{enterprise.id}?#{params.to_query}" 75 get "/api/v1/enterprises/#{enterprise.id}?#{params.to_query}"
76 json = JSON.parse(last_response.body) 76 json = JSON.parse(last_response.body)
@@ -87,8 +87,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -87,8 +87,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
87 end 87 end
88 88
89 should 'list person enterprises' do 89 should 'list person enterprises' do
90 - enterprise = fast_create(Enterprise)  
91 - fast_create(Enterprise) 90 + enterprise = fast_create(Enterprise, :environment_id => environment.id)
  91 + fast_create(Enterprise, :environment_id => environment.id)
92 enterprise.add_member(person) 92 enterprise.add_member(person)
93 93
94 get "/api/v1/people/#{person.id}/enterprises?#{params.to_query}" 94 get "/api/v1/people/#{person.id}/enterprises?#{params.to_query}"
@@ -97,8 +97,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase @@ -97,8 +97,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
97 end 97 end
98 98
99 should 'not list person enterprises invisible' do 99 should 'not list person enterprises invisible' do
100 - c1 = fast_create(Enterprise)  
101 - c2 = fast_create(Enterprise, :visible => false) 100 + c1 = fast_create(Enterprise, :environment_id => environment.id)
  101 + c2 = fast_create(Enterprise, :environment_id => environment.id, :visible => false)
102 c1.add_member(person) 102 c1.add_member(person)
103 c2.add_member(person) 103 c2.add_member(person)
104 104
test/unit/api/helpers_test.rb
@@ -25,15 +25,6 @@ class APIHelpersTest &lt; ActiveSupport::TestCase @@ -25,15 +25,6 @@ class APIHelpersTest &lt; ActiveSupport::TestCase
25 assert_equal user, current_user 25 assert_equal user, current_user
26 end 26 end
27 27
28 - should 'not get the current user 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_nil current_user  
35 - end  
36 -  
37 should 'get the person of current user' do 28 should 'get the person of current user' do
38 user = create_user('someuser') 29 user = create_user('someuser')
39 user.generate_private_token! 30 user.generate_private_token!
@@ -161,6 +152,39 @@ class APIHelpersTest &lt; ActiveSupport::TestCase @@ -161,6 +152,39 @@ class APIHelpersTest &lt; ActiveSupport::TestCase
161 assert_nil make_conditions_with_parameter[:type] 152 assert_nil make_conditions_with_parameter[:type]
162 end 153 end
163 154
  155 + #test_should_make_order_with_parameters_return_order_if attribute_is_found_at_object_association
  156 + should 'make_order_with_parameters return order if attribute is found at object association' do
  157 + environment = Environment.new
  158 + params = {:order => "name ASC"}
  159 + assert_equal "name ASC", make_order_with_parameters(environment, "articles", params)
  160 + end
  161 +
  162 + # test added to check for eventual sql injection vunerabillity
  163 + #test_should_make_order_with_parameters_return_default_order_if_attributes_not_exists
  164 + should 'make_order_with_parameters return default order if attributes not exists' do
  165 + environment = Environment.new
  166 + params = {:order => "CRAZY_FIELD ASC"} # quote used to check sql injection vunerabillity
  167 + assert_equal "created_at DESC", make_order_with_parameters(environment, "articles", params)
  168 + end
  169 +
  170 + should 'make_order_with_parameters return default order if sql injection detected' do
  171 + environment = Environment.new
  172 + params = {:order => "name' ASC"} # quote used to check sql injection vunerabillity
  173 + assert_equal "created_at DESC", make_order_with_parameters(environment, "articles", params)
  174 + end
  175 +
  176 + should 'make_order_with_parameters return RANDOM() if random is passed' do
  177 + environment = Environment.new
  178 + params = {:order => "random"} # quote used to check sql injection vunerabillity
  179 + assert_equal "RANDOM()", make_order_with_parameters(environment, "articles", params)
  180 + end
  181 +
  182 + should 'make_order_with_parameters return RANDOM() if random function is passed' do
  183 + environment = Environment.new
  184 + params = {:order => "random()"} # quote used to check sql injection vunerabillity
  185 + assert_equal "RANDOM()", make_order_with_parameters(environment, "articles", params)
  186 + end
  187 +
164 should 'render not_found if endpoint is unavailable' do 188 should 'render not_found if endpoint is unavailable' do
165 Noosfero::API::API.stubs(:endpoint_unavailable?).returns(true) 189 Noosfero::API::API.stubs(:endpoint_unavailable?).returns(true)
166 self.expects(:not_found!) 190 self.expects(:not_found!)
test/unit/api/people_test.rb
@@ -148,4 +148,21 @@ class PeopleTest &lt; ActiveSupport::TestCase @@ -148,4 +148,21 @@ class PeopleTest &lt; ActiveSupport::TestCase
148 get "/api/v1/people/#{some_person.id}/permissions?#{params.to_query}" 148 get "/api/v1/people/#{some_person.id}/permissions?#{params.to_query}"
149 assert_equal 403, last_response.status 149 assert_equal 403, last_response.status
150 end 150 end
  151 +
  152 + should 'not update another person' do
  153 + person = fast_create(Person, :environment_id => environment.id)
  154 + post "/api/v1/people/#{person.id}?#{params.to_query}"
  155 + assert_equal 403, last_response.status
  156 + end
  157 +
  158 + should 'update yourself' do
  159 + another_name = 'Another Name'
  160 + params[:person] = {}
  161 + params[:person][:name] = another_name
  162 + assert_not_equal another_name, person.name
  163 + post "/api/v1/people/#{person.id}?#{params.to_query}"
  164 + person.reload
  165 + assert_equal another_name, person.name
  166 + end
  167 +
151 end 168 end
test/unit/api/search_test.rb 0 → 100644
@@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
  1 +require_relative 'test_helper'
  2 +
  3 +class SearchTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @person = create_user('testing').person
  7 + end
  8 + attr_reader :person
  9 +
  10 + should 'not list unpublished articles' do
  11 + Article.delete_all
  12 + article = fast_create(Article, :profile_id => person.id, :published => false)
  13 + assert !article.published?
  14 + get "/api/v1/search/article"
  15 + json = JSON.parse(last_response.body)
  16 + assert_empty json['articles']
  17 + end
  18 +
  19 + should 'list articles' do
  20 + fast_create(Article, :profile_id => person.id)
  21 + get "/api/v1/search/article"
  22 + json = JSON.parse(last_response.body)
  23 + assert_not_empty json['articles']
  24 + end
  25 +
  26 + should 'invalid search string articles' do
  27 + fast_create(Article, :profile_id => person.id, :name => 'some article')
  28 + get "/api/v1/search/article?query=test"
  29 + json = JSON.parse(last_response.body)
  30 + assert_empty json['articles']
  31 + end
  32 +
  33 + should 'do not list articles of wrong type' do
  34 + fast_create(Article, :profile_id => person.id)
  35 + get "/api/v1/search/article?type=TinyMceArticle"
  36 + json = JSON.parse(last_response.body)
  37 + assert_empty json['articles']
  38 + end
  39 +
  40 + should 'list articles of one type' do
  41 + fast_create(Article, :profile_id => person.id)
  42 + article = fast_create(TinyMceArticle, :profile_id => person.id)
  43 +
  44 + get "/api/v1/search/article?type=TinyMceArticle"
  45 + json = JSON.parse(last_response.body)
  46 + assert_equal article.id, json['articles'].first['id']
  47 + end
  48 +
  49 + should 'list articles of one type and query string' do
  50 + fast_create(Article, :profile_id => person.id, :name => 'some article')
  51 + fast_create(Article, :profile_id => person.id, :name => 'Some thing')
  52 + article = fast_create(TinyMceArticle, :profile_id => person.id, :name => 'Some thing')
  53 + get "/api/v1/search/article?type=TinyMceArticle&query=thing"
  54 + json = JSON.parse(last_response.body)
  55 + assert_equal 1, json['articles'].count
  56 + assert_equal article.id, json['articles'].first['id']
  57 + end
  58 +
  59 + should 'not return more entries than page limit' do
  60 + 1.upto(5).each do |n|
  61 + fast_create(Article, :profile_id => person.id, :name => "Article #{n}")
  62 + end
  63 +
  64 + get "/api/v1/search/article?query=Article&per_page=3"
  65 + json = JSON.parse(last_response.body)
  66 +
  67 + assert_equal 3, json['articles'].count
  68 + end
  69 +
  70 + should 'return entries second page' do
  71 + 1.upto(5).each do |n|
  72 + fast_create(Article, :profile_id => person.id, :name => "Article #{n}")
  73 + end
  74 +
  75 + get "/api/v1/search/article?query=Article&per_page=3&page=2"
  76 + json = JSON.parse(last_response.body)
  77 +
  78 + assert_equal 2, json['articles'].count
  79 + end
  80 +
  81 + should 'search articles in profile' do
  82 + person2 = fast_create(Person)
  83 + fast_create(Article, :profile_id => person.id)
  84 + fast_create(Article, :profile_id => person.id)
  85 + article = fast_create(Article, :profile_id => person2.id)
  86 +
  87 + get "/api/v1/search/article?query=Article&profile_id=#{person2.id}"
  88 + json = JSON.parse(last_response.body)
  89 + assert_equal article.id, json['articles'].first['id']
  90 + end
  91 +
  92 + should 'search and return values specified in fields parameter' do
  93 + fast_create(Article, :profile_id => person.id)
  94 + get "/api/v1/search/article?fields=title"
  95 + json = JSON.parse(last_response.body)
  96 + assert_not_empty json['articles']
  97 + assert_equal ['title'], json['articles'].first.keys
  98 + end
  99 +
  100 + should 'search with parent' do
  101 + parent = fast_create(Folder, :profile_id => person.id)
  102 + fast_create(Article, :profile_id => person.id)
  103 + article = fast_create(Article, :profile_id => person.id, :parent_id => parent.id)
  104 + get "/api/v1/search/article?parent_id=#{parent.id}"
  105 + json = JSON.parse(last_response.body)
  106 + assert_equal 1, json['articles'].count
  107 + assert_equal article.id, json['articles'].first["id"]
  108 + end
  109 +
  110 + should 'search filter by category' do
  111 + Article.delete_all
  112 + fast_create(Article, :profile_id => person.id)
  113 + article = fast_create(Article, :profile_id => person.id)
  114 + category = fast_create(Category)
  115 + article.categories<< category
  116 + get "/api/v1/search/article?category_ids=#{category.id}"
  117 + json = JSON.parse(last_response.body)
  118 + assert_equal 1, json['articles'].count
  119 + assert_equal article.id, json['articles'].first["id"]
  120 + end
  121 +
  122 + should 'search filter by more than one category' do
  123 + Article.delete_all
  124 + fast_create(Article, :profile_id => person.id)
  125 + article1 = fast_create(Article, :profile_id => person.id)
  126 + article2 = fast_create(Article, :profile_id => person.id)
  127 + category1 = fast_create(Category)
  128 + category2 = fast_create(Category)
  129 + article1.categories<< category1
  130 + article2.categories<< category2
  131 + get "/api/v1/search/article?category_ids[]=#{category1.id}&category_ids[]=#{category2.id}"
  132 + json = JSON.parse(last_response.body)
  133 + ids = [article1.id, article2.id]
  134 + assert_equal 2, json['articles'].count
  135 + assert_includes ids, json['articles'].first["id"]
  136 + assert_includes ids, json['articles'].last["id"]
  137 + end
  138 +
  139 +end
test/unit/api/session_test.rb
@@ -10,7 +10,7 @@ class SessionTest &lt; ActiveSupport::TestCase @@ -10,7 +10,7 @@ class SessionTest &lt; ActiveSupport::TestCase
10 params = {:login => "testapi", :password => "testapi"} 10 params = {:login => "testapi", :password => "testapi"}
11 post "/api/v1/login?#{params.to_query}" 11 post "/api/v1/login?#{params.to_query}"
12 json = JSON.parse(last_response.body) 12 json = JSON.parse(last_response.body)
13 - assert !json["private_token"].blank? 13 + assert !json['user']["private_token"].blank?
14 end 14 end
15 15
16 should 'return 401 when login fails' do 16 should 'return 401 when login fails' do
@@ -21,22 +21,165 @@ class SessionTest &lt; ActiveSupport::TestCase @@ -21,22 +21,165 @@ class SessionTest &lt; ActiveSupport::TestCase
21 end 21 end
22 22
23 should 'register a user' do 23 should 'register a user' do
24 - params = {:login => "newuserapi", :password => "newuserapi", :email => "newuserapi@email.com" } 24 + Environment.default.enable('skip_new_user_email_confirmation')
  25 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
25 post "/api/v1/register?#{params.to_query}" 26 post "/api/v1/register?#{params.to_query}"
26 assert_equal 201, last_response.status 27 assert_equal 201, last_response.status
  28 + json = JSON.parse(last_response.body)
  29 + assert User['newuserapi'].activated?
  30 + assert json['user']['activated']
  31 + assert json['user']['private_token'].present?
  32 + end
  33 +
  34 + should 'register a user with name' do
  35 + Environment.default.enable('skip_new_user_email_confirmation')
  36 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com", :name => "Little John" }
  37 + post "/api/v1/register?#{params.to_query}"
  38 + assert_equal 201, last_response.status
  39 + json = JSON.parse(last_response.body)
  40 + assert json['user']['activated']
  41 + assert json['user']['private_token'].present?
  42 + end
  43 +
  44 + should 'register an inactive user' do
  45 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
  46 + post "/api/v1/register?#{params.to_query}"
  47 + assert_equal 201, last_response.status
  48 + json = JSON.parse(last_response.body)
  49 + assert !json['activated']
  50 + assert json['private_token'].blank?
27 end 51 end
28 52
29 - should 'do not register a user without email' do  
30 - params = {:login => "newuserapi", :password => "newuserapi", :email => nil } 53 + should 'not register a user with invalid login' do
  54 + params = {:login => "c", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
31 post "/api/v1/register?#{params.to_query}" 55 post "/api/v1/register?#{params.to_query}"
32 assert_equal 400, last_response.status 56 assert_equal 400, last_response.status
  57 + json = JSON.parse(last_response.body)
  58 + msg = json['message'].split(':')
  59 + key = msg[0][2, 5]
  60 + val = msg[1][2, 38]
  61 + assert_equal "login", key
  62 + assert_equal "is too short (minimum is 2 characters)", val
33 end 63 end
34 64
35 - should 'do not register a duplicated user' do  
36 - params = {:login => "newuserapi", :password => "newuserapi", :email => "newuserapi@email.com" } 65 + should 'not register a user with invalid login pt' do
  66 + I18n.locale = "pt-BR"
  67 + params = {:lang => "pt-BR", :login => "c", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
37 post "/api/v1/register?#{params.to_query}" 68 post "/api/v1/register?#{params.to_query}"
  69 + assert_equal 400, last_response.status
  70 + json = JSON.parse(last_response.body)
  71 + msg = json['message'].split(':')
  72 + key = msg[0][2, 5]
  73 + val = msg[1][2, 35]
  74 + assert_equal "login", key
  75 + assert val.include? "muito curto"
  76 + end
  77 +
  78 + should 'not register a user without email' do
  79 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => nil }
38 post "/api/v1/register?#{params.to_query}" 80 post "/api/v1/register?#{params.to_query}"
39 assert_equal 400, last_response.status 81 assert_equal 400, last_response.status
40 end 82 end
41 83
  84 + should 'not register a duplicated user' do
  85 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
  86 + post "/api/v1/register?#{params.to_query}"
  87 + post "/api/v1/register?#{params.to_query}"
  88 + assert_equal 400, last_response.status
  89 + json = JSON.parse(last_response.body)
  90 + end
  91 +
  92 + # TODO: Add another test cases to check register situations
  93 + should 'activate a user' do
  94 + params = {
  95 + :login => "newuserapi",
  96 + :password => "newuserapi",
  97 + :password_confirmation => "newuserapi",
  98 + :email => "newuserapi@email.com"
  99 + }
  100 + user = User.new(params)
  101 + user.save!
  102 +
  103 + params = { activation_code: user.activation_code}
  104 + patch "/api/v1/activate?#{params.to_query}"
  105 + assert_equal 200, last_response.status
  106 + end
  107 +
  108 + should 'do not activate a user if admin must approve him' do
  109 + params = {
  110 + :login => "newuserapi",
  111 + :password => "newuserapi",
  112 + :password_confirmation => "newuserapi",
  113 + :email => "newuserapi@email.com",
  114 + :environment => Environment.default
  115 + }
  116 + user = User.new(params)
  117 + user.environment.enable('admin_must_approve_new_users')
  118 + user.save!
  119 +
  120 + params = { activation_code: user.activation_code}
  121 + patch "/api/v1/activate?#{params.to_query}"
  122 + assert_equal 202, last_response.status
  123 + assert_equal 'Waiting for admin moderate user registration', JSON.parse(last_response.body)["message"]
  124 + end
  125 +
  126 + should 'do not activate a user if the token is invalid' do
  127 + params = {
  128 + :login => "newuserapi",
  129 + :password => "newuserapi",
  130 + :password_confirmation => "newuserapi",
  131 + :email => "newuserapi@email.com",
  132 + :environment => Environment.default
  133 + }
  134 + user = User.new(params)
  135 + user.save!
  136 +
  137 + params = { activation_code: '70250abe20cc6a67ef9399cf3286cb998b96aeaf'}
  138 + patch "/api/v1/activate?#{params.to_query}"
  139 + assert_equal 412, last_response.status
  140 + end
  141 +
  142 + should 'create task to change password by user login' do
  143 + user = create_user
  144 + params = {:value => user.login}
  145 + assert_difference 'ChangePassword.count' do
  146 + post "/api/v1/forgot_password?#{params.to_query}"
  147 + end
  148 + end
  149 +
  150 + should 'not create task to change password when user is not found' do
  151 + params = {:value => 'wronglogin'}
  152 + assert_no_difference 'ChangePassword.count' do
  153 + post "/api/v1/forgot_password?#{params.to_query}"
  154 + end
  155 + assert_equal 404, last_response.status
  156 + end
  157 +
  158 + should 'change user password and close task' do
  159 + task = ChangePassword.create!(:requestor => @person)
  160 + params.merge!({:code => task.code, :password => 'secret', :password_confirmation => 'secret'})
  161 + patch "/api/v1/new_password?#{params.to_query}"
  162 + assert_equal Task::Status::FINISHED, task.reload.status
  163 + assert user.reload.authenticated?('secret')
  164 + json = JSON.parse(last_response.body)
  165 + assert_equal user.id, json['user']['id']
  166 + end
  167 +
  168 + should 'do not change user password when password confirmation is wrong' do
  169 + user = create_user
  170 + user.activate
  171 + task = ChangePassword.create!(:requestor => user.person)
  172 + params = {:code => task.code, :password => 'secret', :password_confirmation => 's3cret'}
  173 + patch "/api/v1/new_password?#{params.to_query}"
  174 + assert_equal Task::Status::ACTIVE, task.reload.status
  175 + assert !user.reload.authenticated?('secret')
  176 + assert_equal 400, last_response.status
  177 + end
  178 +
  179 + should 'render not found when provide a wrong code on password change' do
  180 + params = {:code => "wrongcode", :password => 'secret', :password_confirmation => 'secret'}
  181 + patch "/api/v1/new_password?#{params.to_query}"
  182 + assert_equal 404, last_response.status
  183 + end
  184 +
42 end 185 end
test/unit/api/test_helper.rb
1 -require 'test_helper' 1 +require_relative '../../test_helper'
2 2
3 class ActiveSupport::TestCase 3 class ActiveSupport::TestCase
4 4
@@ -9,16 +9,22 @@ class ActiveSupport::TestCase @@ -9,16 +9,22 @@ class ActiveSupport::TestCase
9 end 9 end
10 10
11 def login_api 11 def login_api
12 - @user = User.create!(:login => 'testapi', :password => 'testapi', :password_confirmation => 'testapi', :email => 'test@test.org', :environment => Environment.default) 12 + @environment = Environment.default
  13 + @user = User.create!(:login => 'testapi', :password => 'testapi', :password_confirmation => 'testapi', :email => 'test@test.org', :environment => @environment)
13 @user.activate 14 @user.activate
14 @person = @user.person 15 @person = @user.person
15 16
16 post "/api/v1/login?login=testapi&password=testapi" 17 post "/api/v1/login?login=testapi&password=testapi"
17 json = JSON.parse(last_response.body) 18 json = JSON.parse(last_response.body)
18 @private_token = json["private_token"] 19 @private_token = json["private_token"]
  20 + unless @private_token
  21 + @user.generate_private_token!
  22 + @private_token = @user.private_token
  23 + end
  24 +
19 @params = {:private_token => @private_token} 25 @params = {:private_token => @private_token}
20 end 26 end
21 - attr_accessor :private_token, :user, :person, :params 27 + attr_accessor :private_token, :user, :person, :params, :environment
22 28
23 private 29 private
24 30
test/unit/api/users_test.rb 0 → 100644
@@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
  1 +# encoding: UTF-8
  2 +require_relative 'test_helper'
  3 +
  4 +class UsersTest < ActiveSupport::TestCase
  5 +
  6 + def setup
  7 + login_api
  8 + end
  9 +
  10 + should 'list users' do
  11 + get "/api/v1/users/?#{params.to_query}"
  12 + json = JSON.parse(last_response.body)
  13 + assert_includes json["users"].map { |a| a["login"] }, user.login
  14 + end
  15 +
  16 + should 'get user' do
  17 + get "/api/v1/users/#{user.id}?#{params.to_query}"
  18 + json = JSON.parse(last_response.body)
  19 + assert_equal user.id, json['user']['id']
  20 + end
  21 +
  22 + should 'list user permissions' do
  23 + community = fast_create(Community)
  24 + community.add_admin(person)
  25 + get "/api/v1/users/#{user.id}/?#{params.to_query}"
  26 + json = JSON.parse(last_response.body)
  27 + assert_includes json["user"]["permissions"], community.identifier
  28 + end
  29 +
  30 + should 'get logged user' do
  31 + get "/api/v1/users/me?#{params.to_query}"
  32 + json = JSON.parse(last_response.body)
  33 + assert_equal user.id, json['user']['id']
  34 + end
  35 +
  36 + should 'not show permissions to logged user' do
  37 + target_person = create_user('some-user').person
  38 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  39 + json = JSON.parse(last_response.body)
  40 + refute json["user"].has_key?("permissions")
  41 + end
  42 +
  43 + should 'show permissions to self' do
  44 + get "/api/v1/users/#{user.id}/?#{params.to_query}"
  45 + json = JSON.parse(last_response.body)
  46 + assert json["user"].has_key?("permissions")
  47 + end
  48 +
  49 + should 'not show permissions to friend' do
  50 + target_person = create_user('some-user').person
  51 +
  52 + f = Friendship.new
  53 + f.friend = target_person
  54 + f.person = person
  55 + f.save!
  56 +
  57 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  58 + json = JSON.parse(last_response.body)
  59 + refute json["user"].has_key?("permissions")
  60 + end
  61 +
  62 + should 'not show private attribute to logged user' do
  63 + target_person = create_user('some-user').person
  64 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  65 + json = JSON.parse(last_response.body)
  66 + refute json["user"].has_key?("email")
  67 + end
  68 +
  69 + should 'show private attr to friend' do
  70 + target_person = create_user('some-user').person
  71 + f = Friendship.new
  72 + f.friend = target_person
  73 + f.person = person
  74 + f.save!
  75 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  76 + json = JSON.parse(last_response.body)
  77 + assert json["user"].has_key?("email")
  78 + assert_equal target_person.email, json["user"]["email"]
  79 + end
  80 +
  81 + should 'show public attribute to logged user' do
  82 + target_person = create_user('some-user').person
  83 + target_person.fields_privacy={:email=> 'public'}
  84 + target_person.save!
  85 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  86 + json = JSON.parse(last_response.body)
  87 + assert json["user"].has_key?("email")
  88 + assert_equal json["user"]["email"],target_person.email
  89 + end
  90 +
  91 + should 'show public and private field to admin' do
  92 + Environment.default.add_admin(person)
  93 +
  94 + target_person = create_user('some-user').person
  95 + target_person.fields_privacy={:email=> 'public'}
  96 + target_person.save!
  97 +
  98 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  99 + json = JSON.parse(last_response.body)
  100 + assert json["user"].has_key?("email")
  101 + assert json["user"].has_key?("permissions")
  102 + assert json["user"].has_key?("activated")
  103 + end
  104 +
  105 +end
test/unit/create_thumbnails_job_test.rb
@@ -34,4 +34,16 @@ class CreateThumbnailsJobTest &lt; ActiveSupport::TestCase @@ -34,4 +34,16 @@ class CreateThumbnailsJobTest &lt; ActiveSupport::TestCase
34 end 34 end
35 end 35 end
36 36
  37 + should 'expire cache of articles that use an image that just got a thumbnail' do
  38 + person = create_user('test_user').person
  39 + file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => person)
  40 + article = create(Article, :name => 'test', :image_builder => {
  41 + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')
  42 + }, :profile_id => person.id)
  43 + old_cache_key = article.cache_key
  44 + job = CreateThumbnailsJob.new(file.class.name, file.id)
  45 + job.perform
  46 + process_delayed_job_queue
  47 + assert_not_equal old_cache_key, Article.find(article.id).reload.cache_key
  48 + end
37 end 49 end