Commit 7664b82726b90aa44efa4e783728c6db6736231b

Authored by Rodrigo Souto
1 parent 688b3512

stoa_plugin: improve webservice

   * Creates a smart api to define categories of fields.
   * Inclusion of sensitive and heavy fields categorization
   * Possibility for creation of custom fields

(ActionItem2832)
lib/noosfero/fields_decorator.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +class Noosfero::FieldsDecorator
  2 + attr_accessor :object, :context
  3 +
  4 + def initialize(object, context = nil)
  5 + @object = object
  6 + @context = context
  7 + end
  8 +
  9 + def method_missing(m, *args)
  10 + object.send(m, *args)
  11 + end
  12 +
  13 + def fields(field_names = {})
  14 + field_names.inject({}) { |result, field| result.merge!(field => self.send(field))}
  15 + end
  16 +end
... ...
plugins/stoa/controllers/stoa_plugin_controller.rb
  1 +require 'stoa_plugin/person_fields'
  2 +
1 3 class StoaPluginController < PublicController
2 4 append_view_path File.join(File.dirname(__FILE__) + '/../views')
3 5  
  6 + include StoaPlugin::PersonFields
  7 +
4 8 def authenticate
5 9 if request.ssl? && request.post?
6 10 if params[:login].blank?
... ... @@ -11,22 +15,14 @@ class StoaPluginController &lt; PublicController
11 15 end
12 16 user = User.authenticate(login, params[:password], environment)
13 17 if user
14   - result = {
15   - :username => user.login,
16   - :email => user.email,
17   - :name => user.name,
18   - :nusp => user.person.usp_id,
19   - :first_name => user.name.split(' ').first,
20   - :surname => user.name.split(' ',2).last,
21   - :address => user.person.address,
22   - :homepage => url_for(user.person.url),
23   - }
  18 + result = StoaPlugin::PersonApi.new(user.person, self).fields(selected_fields(params[:fields], user))
  19 + result.merge!(:ok => true)
24 20 else
25   - result = { :error => _('Incorrect user/password pair.') }
  21 + result = { :error => _('Incorrect user/password pair.'), :ok => false }
26 22 end
27 23 render :text => result.to_json
28 24 else
29   - render :text => { :error => _('Conection requires SSL certificate and post method.') }.to_json
  25 + render :text => { :error => _('Conection requires SSL certificate and post method.'), :ok => false }.to_json
30 26 end
31 27 end
32 28  
... ... @@ -46,4 +42,16 @@ class StoaPluginController &lt; PublicController
46 42 end
47 43 end
48 44  
  45 + private
  46 +
  47 + def selected_fields(kind, user)
  48 + fields = FIELDS[kind] || FIELDS['essential']
  49 + return fields.reject { |field| !FIELDS['essential'].include?(field) } unless user.person.public_profile
  50 + fields.reject do |field|
  51 + !user.person.public_fields.include?(field) &&
  52 + SENSITIVE.include?(field) &&
  53 + !FIELDS['essential'].include?(field)
  54 + end
  55 + end
  56 +
49 57 end
... ...
plugins/stoa/lib/stoa_plugin/person_api.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +class StoaPlugin::PersonApi < Noosfero::FieldsDecorator
  2 + def username
  3 + user.login
  4 + end
  5 +
  6 + def nusp
  7 + usp_id
  8 + end
  9 +
  10 + def first_name
  11 + name.split(' ').first
  12 + end
  13 +
  14 + def surname
  15 + name.split(' ',2).last
  16 + end
  17 +
  18 + def homepage
  19 + context.url_for(url)
  20 + end
  21 +
  22 + def image_base64
  23 + Base64.encode64(image.current_data) if image && image.current_data
  24 + end
  25 +end
... ...
plugins/stoa/lib/stoa_plugin/person_fields.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +module StoaPlugin::PersonFields
  2 + HEAVY = %w[image_base64]
  3 + SENSITIVE = %w[]
  4 + FILTER = %w[image]
  5 +
  6 + ESSENTIAL = %w[username email nusp]
  7 + AVERAGE = ESSENTIAL + %w[name first_name surname address homepage]
  8 + FULL = (AVERAGE + Person.fields + HEAVY - FILTER).uniq
  9 + COMPLETE = FULL - HEAVY
  10 +
  11 + FIELDS = {
  12 + 'none' => {},
  13 + 'essential' => ESSENTIAL,
  14 + 'average' => AVERAGE,
  15 + 'full' => FULL,
  16 + 'complete' => COMPLETE
  17 + }
  18 +end
... ...
plugins/stoa/test/functional/stoa_plugin_controller_test.rb
... ... @@ -54,6 +54,114 @@ class StoaPluginControllerTest &lt; ActionController::TestCase
54 54 assert_equal user.login, json_response['username']
55 55 end
56 56  
  57 + should 'authenticate with usp_id' do
  58 + @request.stubs(:ssl?).returns(true)
  59 + post :authenticate, :usp_id => user.person.usp_id.to_s, :password => '123456'
  60 +
  61 + assert_nil json_response['error']
  62 + assert_equal user.login, json_response['username']
  63 + end
  64 +
  65 + should 'return no fields if fields requested was none' do
  66 + @request.stubs(:ssl?).returns(true)
  67 + post :authenticate, :login => user.login, :password => '123456', :fields => 'none'
  68 +
  69 + expected_response = {'ok' => true}
  70 +
  71 + assert_nil json_response['error']
  72 + assert_equal expected_response, json_response
  73 + end
  74 +
  75 + should 'return only the essential fields if no fields requested' do
  76 + @request.stubs(:ssl?).returns(true)
  77 + post :authenticate, :login => user.login, :password => '123456'
  78 + response = json_response.clone
  79 +
  80 + assert_nil response['error']
  81 + assert_equal true, response.delete('ok')
  82 + assert_equal user.login, response.delete('username')
  83 + assert_equal user.email, response.delete('email')
  84 + assert_equal user.person.usp_id.to_s, response.delete('nusp')
  85 + assert response.blank?
  86 + end
  87 +
  88 + should 'return only selected fields' do
  89 + @request.stubs(:ssl?).returns(true)
  90 + Person.any_instance.stubs(:f1).returns('field1')
  91 + Person.any_instance.stubs(:f2).returns('field2')
  92 + Person.any_instance.stubs(:f3).returns('field3')
  93 + @controller.stubs(:selected_fields).returns(%w[f1 f2 f3])
  94 +
  95 + post :authenticate, :login => user.login, :password => '123456', :fields => 'special'
  96 + response = json_response.clone
  97 +
  98 + assert_equal true, response.delete('ok')
  99 + assert_equal 'field1', response.delete('f1')
  100 + assert_equal 'field2', response.delete('f2')
  101 + assert_equal 'field3', response.delete('f3')
  102 + assert response.blank?
  103 + end
  104 +
  105 + should 'not return sensitive fields that are private' do
  106 + @request.stubs(:ssl?).returns(true)
  107 + Person.any_instance.stubs(:f1).returns('field1')
  108 + Person.any_instance.stubs(:f2).returns('field2')
  109 + Person.any_instance.stubs(:f3).returns('field3')
  110 + StoaPluginController::FIELDS['special'] = %w[f1 f2 f3]
  111 + StoaPluginController::SENSITIVE = %w[f1 f2]
  112 + person = user.person
  113 + person.fields_privacy = {:f1 => 'private', :f2 => 'public', :f3 => 'public'}
  114 + person.save!
  115 +
  116 + post :authenticate, :login => user.login, :password => '123456', :fields => 'special'
  117 +
  118 + assert !json_response.keys.include?('f1')
  119 + assert json_response.keys.include?('f2')
  120 + assert json_response.keys.include?('f3')
  121 + end
  122 +
  123 + should 'return essential fields even if they are sensitive and private' do
  124 + @request.stubs(:ssl?).returns(true)
  125 + StoaPluginController::SENSITIVE = %w[email]
  126 + person = user.person
  127 + person.fields_privacy = {:email => 'private'}
  128 + person.save!
  129 +
  130 + post :authenticate, :login => user.login, :password => '123456'
  131 +
  132 + assert json_response.keys.include?('email')
  133 + end
  134 +
  135 + should 'return only essential fields when profile is private' do
  136 + @request.stubs(:ssl?).returns(true)
  137 + Person.any_instance.stubs(:f1).returns('field1')
  138 + Person.any_instance.stubs(:f2).returns('field2')
  139 + Person.any_instance.stubs(:f3).returns('field3')
  140 + StoaPluginController::FIELDS['special'] = %w[f1 f2 f3] + StoaPluginController::FIELDS['essential']
  141 + person = user.person
  142 + person.public_profile = false
  143 + person.save!
  144 +
  145 + post :authenticate, :login => user.login, :password => '123456', :fields => 'special'
  146 + response = json_response.clone
  147 +
  148 + assert_nil response['error']
  149 + assert_equal true, response.delete('ok')
  150 + assert_equal user.login, response.delete('username')
  151 + assert_equal user.email, response.delete('email')
  152 + assert_equal user.person.usp_id.to_s, response.delete('nusp')
  153 + assert response.blank?
  154 + end
  155 +
  156 + should 'not crash if usp_id is invalid' do
  157 + @request.stubs(:ssl?).returns(true)
  158 + assert_nothing_raised do
  159 + post :authenticate, :usp_id => 12321123, :password => '123456'
  160 + end
  161 + assert_not_nil json_response['error']
  162 + assert_match /user/,json_response['error']
  163 + end
  164 +
57 165 should 'check valid usp id' do
58 166 usp_id = '12345678'
59 167 StoaPlugin::UspUser.stubs(:exists?).with(usp_id).returns(true)
... ... @@ -91,23 +199,6 @@ class StoaPluginControllerTest &lt; ActionController::TestCase
91 199 assert !json_response['exists']
92 200 end
93 201  
94   - should 'authenticate with usp_id' do
95   - @request.stubs(:ssl?).returns(true)
96   - post :authenticate, :usp_id => user.person.usp_id.to_s, :password => '123456'
97   -
98   - assert_nil json_response['error']
99   - assert_equal user.login, json_response['username']
100   - end
101   -
102   - should 'not crash if usp_id is invalid' do
103   - @request.stubs(:ssl?).returns(true)
104   - assert_nothing_raised do
105   - post :authenticate, :usp_id => 12321123, :password => '123456'
106   - end
107   - assert_not_nil json_response['error']
108   - assert_match /user/,json_response['error']
109   - end
110   -
111 202 private
112 203  
113 204 def json_response
... ...