Commit c4d1dd86e0e1ef06d8a085bc4cf87ac7423f27fd

Authored by Victor Costa
2 parents 3a9e86d7 ef5a4c0a

Merge branch 'api' into production

Conflicts:
	test/fixtures/article_followers.yml
app/models/environment.rb
@@ -326,6 +326,9 @@ class Environment < ActiveRecord::Base @@ -326,6 +326,9 @@ class Environment < ActiveRecord::Base
326 326
327 settings_items :signup_welcome_screen_body, :type => String 327 settings_items :signup_welcome_screen_body, :type => String
328 328
  329 + #Captcha setings
  330 + settings_items :api_captcha_settings, :type => ActiveSupport::HashWithIndifferentAccess, :default => {}
  331 +
329 def has_custom_welcome_screen? 332 def has_custom_welcome_screen?
330 settings[:signup_welcome_screen_body].present? 333 settings[:signup_welcome_screen_body].present?
331 end 334 end
app/models/user.rb
@@ -129,7 +129,8 @@ class User < ActiveRecord::Base @@ -129,7 +129,8 @@ class User < ActiveRecord::Base
129 end 129 end
130 130
131 #FIXME make this test 131 #FIXME make this test
132 - def private_token_expired? 132 + def private_token_expired?
  133 + return true if self.private_token_generated_at.nil?
133 self.generate_private_token! if self.private_token.nil? || (self.private_token_generated_at + 2.weeks < DateTime.now) 134 self.generate_private_token! if self.private_token.nil? || (self.private_token_generated_at + 2.weeks < DateTime.now)
134 end 135 end
135 136
@@ -357,19 +358,6 @@ class User &lt; ActiveRecord::Base @@ -357,19 +358,6 @@ class User &lt; ActiveRecord::Base
357 @is_password_required = false 358 @is_password_required = false
358 end 359 end
359 360
360 - #FIXME make this test  
361 - def generate_private_token!  
362 - self.private_token = SecureRandom.hex  
363 - self.private_token_generated_at = DateTime.now  
364 - save(:validate => false)  
365 - end  
366 -  
367 - #FIXME make this test  
368 - def private_token_expired?  
369 - self.generate_private_token! if self.private_token.nil? || (self.private_token_generated_at + 2.weeks < DateTime.now)  
370 - end  
371 -  
372 -  
373 protected 361 protected
374 362
375 def normalize_email 363 def normalize_email
lib/noosfero/api/api.rb
1 require 'grape' 1 require 'grape'
2 #require 'rack/contrib' 2 #require 'rack/contrib'
  3 +Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require_dependency file unless file =~ /api\.rb/}
3 4
4 -Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file unless file =~ /api\.rb/}  
5 module Noosfero 5 module Noosfero
6 module API 6 module API
7 class API < Grape::API 7 class API < Grape::API
@@ -12,6 +12,13 @@ module Noosfero @@ -12,6 +12,13 @@ module Noosfero
12 use GrapeLogging::Middleware::RequestLogger, { logger: logger } 12 use GrapeLogging::Middleware::RequestLogger, { logger: logger }
13 13
14 rescue_from :all do |e| 14 rescue_from :all do |e|
  15 + # Many brave warriors have fallen in the battle for fixing the API log
  16 + # Please, don't remove these 2 lines until the API log problem has
  17 + # been PROPERLY fixed by our savior!!!
  18 + # Otherwise we will have no clue of what went wrong in the API
  19 + puts "API error during processing: #{$!}"
  20 + puts "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
  21 + # Thanks!
15 logger.error e 22 logger.error e
16 end 23 end
17 24
@@ -61,4 +68,4 @@ module Noosfero @@ -61,4 +68,4 @@ module Noosfero
61 end 68 end
62 end 69 end
63 end 70 end
64 -end 71 -end
  72 +end
65 \ No newline at end of file 73 \ No newline at end of file
lib/noosfero/api/helpers.rb
@@ -4,6 +4,8 @@ @@ -4,6 +4,8 @@
4 PRIVATE_TOKEN_PARAM = :private_token 4 PRIVATE_TOKEN_PARAM = :private_token
5 ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type] 5 ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type]
6 6
  7 + include SanitizeParams
  8 +
7 def current_user 9 def current_user
8 private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s 10 private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s
9 @current_user ||= User.find_by_private_token(private_token) 11 @current_user ||= User.find_by_private_token(private_token)
@@ -91,6 +93,7 @@ @@ -91,6 +93,7 @@
91 end 93 end
92 94
93 def authenticate! 95 def authenticate!
  96 +
94 unauthorized! unless current_user 97 unauthorized! unless current_user
95 end 98 end
96 99
@@ -207,39 +210,29 @@ @@ -207,39 +210,29 @@
207 # captcha_helpers # 210 # captcha_helpers #
208 ########################################## 211 ##########################################
209 212
210 - def test_captcha(remote_ip, params)  
211 - return true unless API.NOOSFERO_CONF['api_captcha_enabled'] === true  
212 -  
213 - private_key = API.NOOSFERO_CONF['api_recaptcha_private_key']  
214 - if private_key == nil  
215 - raise ArgumentError, "API.NOOSFERO_CONF['api_recaptcha_private_key'] not defined"  
216 - end  
217 -  
218 - api_captcha_version = API.NOOSFERO_CONF['api_captcha_version']  
219 - unless api_captcha_version == 1 || api_captcha_version == 2  
220 - raise ArgumentError, "API.NOOSFERO_CONF['api_captcha_version'] not defined"  
221 - end  
222 -  
223 - if api_captcha_version == 1  
224 - api_recaptcha_verify_uri = API.NOOSFERO_CONF['api_recaptcha_v1_verify_uri']  
225 - if api_recaptcha_verify_uri == nil  
226 - raise ArgumentError, "API.NOOSFERO_CONF['api_recaptcha_v1_verify_uri'] not defined" 213 + def test_captcha(remote_ip, params, _environment = nil)
  214 + environment ||= _environment
  215 + d = environment.api_captcha_settings
  216 + return true unless d[:enabled] == true
  217 +
  218 + if d[:provider] == 'google'
  219 + raise ArgumentError, "Environment api_captcha_settings private_key not defined" if d[:private_key].nil?
  220 + raise ArgumentError, "Environment api_captcha_settings version not defined" unless d[:version] == 1 || d[:version] == 2
  221 + raise ArgumentError, "Environment api_captcha_settings verify_uri not defined" if d[:verify_uri].nil?
  222 + if d[:version] == 1
  223 + return verify_recaptcha_v1(remote_ip, d[:private_key], d[:verify_uri], params[:recaptcha_challenge_field], params[:recaptcha_response_field])
227 end 224 end
228 - return verify_recaptcha_v1(remote_ip, private_key, api_recaptcha_verify_uri, params[:recaptcha_challenge_field], params[:recaptcha_response_field])  
229 - end  
230 -  
231 - if api_captcha_version == 2  
232 - api_recaptcha_verify_uri = API.NOOSFERO_CONF['api_recaptcha_v2_verify_uri']  
233 - if api_recaptcha_verify_uri == nil  
234 - raise ArgumentError, "API.NOOSFERO_CONF['api_recaptcha_v2_verify_uri'] not defined" 225 + if d[:version] == 2
  226 + return verify_recaptcha_v2(remote_ip, d[:private_key], d[:verify_uri], params[:g_recaptcha_response])
235 end 227 end
236 - return verify_recaptcha_v2(remote_ip, private_key, api_recaptcha_verify_uri, params[:g_recaptcha_response])  
237 end 228 end
238 229
  230 + if d[:provider] == 'serpro'
  231 + #TODO ADD SERPRO's CAPTCHA
  232 + end
239 end 233 end
240 234
241 def verify_recaptcha_v1(remote_ip, private_key, api_recaptcha_verify_uri, recaptcha_challenge_field, recaptcha_response_field) 235 def verify_recaptcha_v1(remote_ip, private_key, api_recaptcha_verify_uri, recaptcha_challenge_field, recaptcha_response_field)
242 -  
243 if recaptcha_challenge_field == nil || recaptcha_response_field == nil 236 if recaptcha_challenge_field == nil || recaptcha_response_field == nil
244 return _('Missing captcha data') 237 return _('Missing captcha data')
245 end 238 end
lib/noosfero/api/session.rb
@@ -29,7 +29,7 @@ module Noosfero @@ -29,7 +29,7 @@ module Noosfero
29 # password (required) - Password 29 # password (required) - Password
30 # login - login 30 # login - login
31 # Example Request: 31 # Example Request:
32 - # POST /register?email=some@mail.com&password=pas&login=some 32 + # POST /register?email=some@mail.com&password=pas&password_confirmation=pas&login=some
33 params do 33 params do
34 requires :email, type: String, desc: _("Email") 34 requires :email, type: String, desc: _("Email")
35 requires :login, type: String, desc: _("Login") 35 requires :login, type: String, desc: _("Login")
lib/sanitize_params.rb
@@ -2,33 +2,40 @@ module SanitizeParams @@ -2,33 +2,40 @@ module SanitizeParams
2 2
3 protected 3 protected
4 4
5 - # Check each request parameter for  
6 - # improper HTML or Script tags  
7 - def sanitize_params  
8 - request.params.each { |k, v|  
9 - if v.is_a?(String)  
10 - params[k] = sanitize_param v  
11 - elsif v.is_a?(Array)  
12 - params[k] = sanitize_array v  
13 - end  
14 - }  
15 - end 5 + # Check each request parameter for
  6 + # improper HTML or Script tags
  7 + def sanitize_params
  8 + sanitize_params_hash(request.params)
  9 + end
16 10
17 - # If the parameter was an array,  
18 - # try to sanitize each element in the array  
19 - def sanitize_array(array)  
20 - array.map! { |e|  
21 - if e.is_a?(String)  
22 - sanitize_param e  
23 - end  
24 - }  
25 - return array  
26 - end 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
27 23
28 - # Santitize a single value  
29 - def sanitize_param(value)  
30 - 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)  
31 - ActionController::Base.helpers.sanitize(value, tags: allowed_tags, attributes: %w(href title))  
32 - end 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
33 40
34 end 41 end
test/unit/api/helpers_test.rb
@@ -161,6 +161,46 @@ class APIHelpersTest &lt; ActiveSupport::TestCase @@ -161,6 +161,46 @@ class APIHelpersTest &lt; ActiveSupport::TestCase
161 assert_nil make_conditions_with_parameter[:type] 161 assert_nil make_conditions_with_parameter[:type]
162 end 162 end
163 163
  164 + should 'do not test captcha when there are no settings' do
  165 + environment = Environment.new
  166 + assert test_captcha("127.0.0.1", {}, environment)
  167 + end
  168 +
  169 + should 'do not test captcha when captcha is disabled on settings' do
  170 + environment = Environment.new
  171 + environment.api_captcha_settings = {
  172 + enabled: false,
  173 + }
  174 + assert test_captcha("127.0.0.1", {}, environment)
  175 + end
  176 +
  177 +
  178 + should 'fail display recaptcha v1' do
  179 + environment = Environment.new
  180 + environment.api_captcha_settings = {
  181 + enabled: true,
  182 + provider: 'google',
  183 + version: 1,
  184 + private_key: '6LdsWAcTAAAAAB6maB_HalVyCc4asDAxPxloIMvY',
  185 + public_key: '6LdsWAcTAAAAAChTUUD6yu9fCDhdIZzNd7F53zf-',
  186 + verify_uri: 'https://www.google.com/recaptcha/api/verify',
  187 + }
  188 + assert_equal test_captcha("127.0.0.1", {}, environment), "Missing captcha data"
  189 + end
  190 +
  191 + should 'fail display recaptcha v2' do
  192 + environment = Environment.new
  193 + environment.api_captcha_settings = {
  194 + enabled: true,
  195 + provider: 'google',
  196 + version: 2,
  197 + private_key: '6LdsWAcTAAAAAB6maB_HalVyCc4asDAxPxloIMvY',
  198 + public_key: '6LdsWAcTAAAAAChTUUD6yu9fCDhdIZzNd7F53zf-',
  199 + verify_uri: 'https://www.google.com/recaptcha/api/siteverify',
  200 + }
  201 + assert_equal test_captcha("127.0.0.1", {}, environment), "Missing captcha data"
  202 + end
  203 +
164 protected 204 protected
165 205
166 def error!(info, status) 206 def error!(info, status)