Commit b4707ba4a1d2ae12fecedbab85fc33774ec45fd1

Authored by Leandro Santos
2 parents 5fc16fc4 648ba45f

Merge branch 'api' of gitlab.com:participa/noosfero into serpro_api

lib/noosfero/api/api.rb
... ... @@ -29,6 +29,7 @@ module Noosfero
29 29 before { setup_multitenancy }
30 30 before { detect_stuff_by_domain }
31 31 before { filter_disabled_plugins_endpoints }
  32 + before { init_noosfero_plugins }
32 33 after { set_session_cookie }
33 34  
34 35 version 'v1'
... ...
lib/noosfero/api/entities.rb
... ... @@ -113,6 +113,7 @@ module Noosfero
113 113 expose :id
114 114 expose :login
115 115 expose :person, :using => Profile
  116 + expose :activated?, as: :activated
116 117 expose :permissions do |user, options|
117 118 output = {}
118 119 user.person.role_assignments.map do |role_assigment|
... ...
lib/noosfero/api/helpers.rb
... ... @@ -6,11 +6,18 @@
6 6 DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type]
7 7  
8 8 include SanitizeParams
  9 + include Noosfero::Plugin::HotSpot
  10 + include ForgotPasswordHelper
9 11  
10 12 def set_locale
11 13 I18n.locale = (params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
12 14 end
13   -
  15 +
  16 + # FIXME this filter just loads @plugins
  17 + def init_noosfero_plugins
  18 + plugins
  19 + end
  20 +
14 21 def current_user
15 22 private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s
16 23 @current_user ||= User.find_by_private_token(private_token)
... ... @@ -57,7 +64,7 @@
57 64  
58 65 def find_article(articles, id)
59 66 article = articles.find(id)
60   - article.display_to?(current_user.person) ? article : forbidden!
  67 + article.display_to?(current_person) ? article : forbidden!
61 68 end
62 69  
63 70 def post_article(asset, params)
... ... @@ -350,6 +357,7 @@
350 357 begin
351 358 body = https.request(request).body
352 359 rescue Exception => e
  360 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
353 361 logger.error e
354 362 return _("Google recaptcha error: #{e.message}")
355 363 end
... ... @@ -375,6 +383,7 @@
375 383 begin
376 384 body = https.request(request).body
377 385 rescue Exception => e
  386 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
378 387 logger.error e
379 388 return _("Google recaptcha error: #{e.message}")
380 389 end
... ... @@ -393,6 +402,7 @@
393 402 begin
394 403 body = http.request(request).body
395 404 rescue Exception => e
  405 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
396 406 logger.error e
397 407 return _("Serpro captcha error: #{e.message}")
398 408 end
... ...
lib/noosfero/api/session.rb
... ... @@ -41,21 +41,96 @@ module Noosfero
41 41 attrs = attributes_for_keys [:email, :login, :password, :password_confirmation] + environment.signup_person_fields
42 42 remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
43 43  
44   - unless test_captcha(remote_ip, params, environment) == true
45   - render_api_error!(_('Please solve the test in order to register.'), 401)
  44 + result = test_captcha(remote_ip, params, environment)
  45 + unless result == true
  46 + render_api_error!(result, 401)
46 47 return
47 48 end
48 49  
49 50 user = User.new(attrs)
50   - if user.save
51   - user.activate
52   - user.generate_private_token!
  51 + if user.save
  52 + user.generate_private_token! if user.activated?
53 53 present user, :with => Entities::UserLogin
54 54 else
55 55 message = user.errors.to_json
56 56 render_api_error!(message, 400)
57 57 end
58 58 end
  59 +
  60 + params do
  61 + requires :activation_code, type: String, desc: _("Activation token")
  62 + end
  63 +
  64 + # Activate a user.
  65 + #
  66 + # Parameter:
  67 + # activation_code (required) - Activation token
  68 + # Example Request:
  69 + # PATCH /activate?activation_code=28259abd12cc6a64ef9399cf3286cb998b96aeaf
  70 + patch "/activate" do
  71 + user = User.find_by_activation_code(params[:activation_code])
  72 + if user
  73 + unless user.environment.enabled?('admin_must_approve_new_users')
  74 + if user.activate
  75 + user.generate_private_token!
  76 + present user, :with => Entities::UserLogin
  77 + end
  78 + else
  79 + if user.create_moderate_task
  80 + user.activation_code = nil
  81 + user.save!
  82 +
  83 + # Waiting for admin moderate user registration
  84 + status 202
  85 + body({
  86 + :message => 'Waiting for admin moderate user registration'
  87 + })
  88 + end
  89 + end
  90 + else
  91 + # Token not found in database
  92 + render_api_error!(_('Token is invalid'), 412)
  93 + end
  94 + end
  95 +
  96 + # Request a new password.
  97 + #
  98 + # Parameters:
  99 + # value (required) - Email or login
  100 + # Example Request:
  101 + # POST /forgot_password?value=some@mail.com
  102 + post "/forgot_password" do
  103 + requestors = fetch_requestors(params[:value])
  104 + not_found! if requestors.blank?
  105 +
  106 + requestors.each do |requestor|
  107 + ChangePassword.create!(:requestor => requestor)
  108 + end
  109 + end
  110 +
  111 + params do
  112 + requires :code, type: String, desc: _("Forgot password code")
  113 + end
  114 + # Change password
  115 + #
  116 + # Parameters:
  117 + # code (required) - Change password code
  118 + # password (required)
  119 + # password_confirmation (required)
  120 + # Example Request:
  121 + # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret
  122 + patch "/new_password" do
  123 + change_password = ChangePassword.find_by_code(params[:code])
  124 + not_found! if change_password.nil?
  125 +
  126 + if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation])
  127 + change_password.finish
  128 + present change_password.requestor.user, :with => Entities::UserLogin
  129 + else
  130 + something_wrong!
  131 + end
  132 + end
  133 +
59 134 end
60 135 end
61 136 end
... ...
lib/noosfero/api/v1/articles.rb
... ... @@ -96,7 +96,7 @@ module Noosfero
96 96 #TODO make tests for this situation
97 97 votes_order = params.delete(:order) if params[:order]=='votes_score'
98 98 articles = select_filtered_collection_of(article, 'children', params)
99   - articles = articles.display_filter(current_person, nil)
  99 + articles = articles.display_filter(current_person, article.profile)
100 100  
101 101  
102 102 #TODO make tests for this situation
... ...
test/unit/api/articles_test.rb
... ... @@ -48,6 +48,15 @@ class ArticlesTest < ActiveSupport::TestCase
48 48 assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] }
49 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 60 should 'not list children of forbidden article' do
52 61 person = fast_create(Person, :environment_id => environment.id)
53 62 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
... ...
test/unit/api/helpers_test.rb
... ... @@ -236,7 +236,7 @@ class APIHelpersTest < ActiveSupport::TestCase
236 236  
237 237 end
238 238  
239   - should 'captcha serpro say Name or service not known' do
  239 + should 'captcha serpro say name or service not known' do
240 240 environment = Environment.new
241 241 environment.api_captcha_settings = {
242 242 enabled: true,
... ...
test/unit/api/session_test.rb
... ... @@ -21,9 +21,22 @@ class SessionTest < ActiveSupport::TestCase
21 21 end
22 22  
23 23 should 'register a user' do
  24 + Environment.default.enable('skip_new_user_email_confirmation')
24 25 params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
25 26 post "/api/v1/register?#{params.to_query}"
26 27 assert_equal 201, last_response.status
  28 + json = JSON.parse(last_response.body)
  29 + assert json['activated']
  30 + assert json['private_token'].present?
  31 + end
  32 +
  33 + should 'register an inactive user' do
  34 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
  35 + post "/api/v1/register?#{params.to_query}"
  36 + assert_equal 201, last_response.status
  37 + json = JSON.parse(last_response.body)
  38 + assert !json['activated']
  39 + assert json['private_token'].blank?
27 40 end
28 41  
29 42 should 'do not register a user without email' do
... ... @@ -39,4 +52,112 @@ class SessionTest < ActiveSupport::TestCase
39 52 assert_equal 400, last_response.status
40 53 end
41 54  
  55 + should 'detected error, Name or service not known, for Serpro Captcha communication' do
  56 + environment = Environment.default
  57 + environment.api_captcha_settings = {
  58 + enabled: true,
  59 + provider: 'serpro',
  60 + serpro_client_id: '0000000000000000',
  61 + verify_uri: 'http://someserverthatdoesnotexist.mycompanythatdoesnotexist.com/validate',
  62 + }
  63 + environment.save!
  64 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com",
  65 + :txtToken_captcha_serpro_gov_br => '4324343', :captcha_text => '4030320'}
  66 + post "/api/v1/register?#{params.to_query}"
  67 + assert_equal "Serpro captcha error: getaddrinfo: Name or service not known", JSON.parse(last_response.body)["message"]
  68 + end
  69 +
  70 + # TODO: Add another test cases to check register situations
  71 + should 'activate a user' do
  72 + params = {
  73 + :login => "newuserapi",
  74 + :password => "newuserapi",
  75 + :password_confirmation => "newuserapi",
  76 + :email => "newuserapi@email.com"
  77 + }
  78 + user = User.new(params)
  79 + user.save!
  80 +
  81 + params = { activation_code: user.activation_code}
  82 + patch "/api/v1/activate?#{params.to_query}"
  83 + assert_equal 200, last_response.status
  84 + end
  85 +
  86 + should 'do not activate a user if admin must approve him' do
  87 + params = {
  88 + :login => "newuserapi",
  89 + :password => "newuserapi",
  90 + :password_confirmation => "newuserapi",
  91 + :email => "newuserapi@email.com",
  92 + :environment => Environment.default
  93 + }
  94 + user = User.new(params)
  95 + user.environment.enable('admin_must_approve_new_users')
  96 + user.save!
  97 +
  98 + params = { activation_code: user.activation_code}
  99 + patch "/api/v1/activate?#{params.to_query}"
  100 + assert_equal 202, last_response.status
  101 + assert_equal 'Waiting for admin moderate user registration', JSON.parse(last_response.body)["message"]
  102 + end
  103 +
  104 + should 'do not activate a user if the token is invalid' do
  105 + params = {
  106 + :login => "newuserapi",
  107 + :password => "newuserapi",
  108 + :password_confirmation => "newuserapi",
  109 + :email => "newuserapi@email.com",
  110 + :environment => Environment.default
  111 + }
  112 + user = User.new(params)
  113 + user.save!
  114 +
  115 + params = { activation_code: '70250abe20cc6a67ef9399cf3286cb998b96aeaf'}
  116 + patch "/api/v1/activate?#{params.to_query}"
  117 + assert_equal 412, last_response.status
  118 + end
  119 +
  120 + should 'create task to change password by user login' do
  121 + user = create_user
  122 + params = {:value => user.login}
  123 + assert_difference 'ChangePassword.count' do
  124 + post "/api/v1/forgot_password?#{params.to_query}"
  125 + end
  126 + end
  127 +
  128 + should 'not create task to change password when user is not found' do
  129 + params = {:value => 'wronglogin'}
  130 + assert_no_difference 'ChangePassword.count' do
  131 + post "/api/v1/forgot_password?#{params.to_query}"
  132 + end
  133 + assert_equal 404, last_response.status
  134 + end
  135 +
  136 + should 'change user password and close task' do
  137 + user = create_user
  138 + task = ChangePassword.create!(:requestor => user.person)
  139 + params = {:code => task.code, :password => 'secret', :password_confirmation => 'secret'}
  140 + patch "/api/v1/new_password?#{params.to_query}"
  141 + assert_equal Task::Status::FINISHED, task.reload.status
  142 + assert user.reload.authenticated?('secret')
  143 + json = JSON.parse(last_response.body)
  144 + assert_equal user.id, json['id']
  145 + end
  146 +
  147 + should 'do not change user password when password confirmation is wrong' do
  148 + user = create_user
  149 + task = ChangePassword.create!(:requestor => user.person)
  150 + params = {:code => task.code, :password => 'secret', :password_confirmation => 's3cret'}
  151 + patch "/api/v1/new_password?#{params.to_query}"
  152 + assert_equal Task::Status::ACTIVE, task.reload.status
  153 + assert !user.reload.authenticated?('secret')
  154 + assert_equal 400, last_response.status
  155 + end
  156 +
  157 + should 'render not found when provide a wrong code on password change' do
  158 + params = {:code => "wrongcode", :password => 'secret', :password_confirmation => 'secret'}
  159 + patch "/api/v1/new_password?#{params.to_query}"
  160 + assert_equal 404, last_response.status
  161 + end
  162 +
42 163 end
... ...