diff --git a/lib/noosfero/fields_decorator.rb b/lib/noosfero/fields_decorator.rb new file mode 100644 index 0000000..dac3068 --- /dev/null +++ b/lib/noosfero/fields_decorator.rb @@ -0,0 +1,16 @@ +class Noosfero::FieldsDecorator + attr_accessor :object, :context + + def initialize(object, context = nil) + @object = object + @context = context + end + + def method_missing(m, *args) + object.send(m, *args) + end + + def fields(field_names = {}) + field_names.inject({}) { |result, field| result.merge!(field => self.send(field))} + end +end diff --git a/plugins/stoa/controllers/stoa_plugin_controller.rb b/plugins/stoa/controllers/stoa_plugin_controller.rb index 96d03a8..988e7bb 100644 --- a/plugins/stoa/controllers/stoa_plugin_controller.rb +++ b/plugins/stoa/controllers/stoa_plugin_controller.rb @@ -1,6 +1,10 @@ +require 'stoa_plugin/person_fields' + class StoaPluginController < PublicController append_view_path File.join(File.dirname(__FILE__) + '/../views') + include StoaPlugin::PersonFields + def authenticate if request.ssl? && request.post? if params[:login].blank? @@ -11,22 +15,14 @@ class StoaPluginController < PublicController end user = User.authenticate(login, params[:password], environment) if user - result = { - :username => user.login, - :email => user.email, - :name => user.name, - :nusp => user.person.usp_id, - :first_name => user.name.split(' ').first, - :surname => user.name.split(' ',2).last, - :address => user.person.address, - :homepage => url_for(user.person.url), - } + result = StoaPlugin::PersonApi.new(user.person, self).fields(selected_fields(params[:fields], user)) + result.merge!(:ok => true) else - result = { :error => _('Incorrect user/password pair.') } + result = { :error => _('Incorrect user/password pair.'), :ok => false } end render :text => result.to_json else - render :text => { :error => _('Conection requires SSL certificate and post method.') }.to_json + render :text => { :error => _('Conection requires SSL certificate and post method.'), :ok => false }.to_json end end @@ -46,4 +42,16 @@ class StoaPluginController < PublicController end end + private + + def selected_fields(kind, user) + fields = FIELDS[kind] || FIELDS['essential'] + return fields.reject { |field| !FIELDS['essential'].include?(field) } unless user.person.public_profile + fields.reject do |field| + !user.person.public_fields.include?(field) && + SENSITIVE.include?(field) && + !FIELDS['essential'].include?(field) + end + end + end diff --git a/plugins/stoa/lib/stoa_plugin/person_api.rb b/plugins/stoa/lib/stoa_plugin/person_api.rb new file mode 100644 index 0000000..65760a3 --- /dev/null +++ b/plugins/stoa/lib/stoa_plugin/person_api.rb @@ -0,0 +1,25 @@ +class StoaPlugin::PersonApi < Noosfero::FieldsDecorator + def username + user.login + end + + def nusp + usp_id + end + + def first_name + name.split(' ').first + end + + def surname + name.split(' ',2).last + end + + def homepage + context.url_for(url) + end + + def image_base64 + Base64.encode64(image.current_data) if image && image.current_data + end +end diff --git a/plugins/stoa/lib/stoa_plugin/person_fields.rb b/plugins/stoa/lib/stoa_plugin/person_fields.rb new file mode 100644 index 0000000..d848af5 --- /dev/null +++ b/plugins/stoa/lib/stoa_plugin/person_fields.rb @@ -0,0 +1,18 @@ +module StoaPlugin::PersonFields + HEAVY = %w[image_base64] + SENSITIVE = %w[] + FILTER = %w[image] + + ESSENTIAL = %w[username email nusp] + AVERAGE = ESSENTIAL + %w[name first_name surname address homepage] + FULL = (AVERAGE + Person.fields + HEAVY - FILTER).uniq + COMPLETE = FULL - HEAVY + + FIELDS = { + 'none' => {}, + 'essential' => ESSENTIAL, + 'average' => AVERAGE, + 'full' => FULL, + 'complete' => COMPLETE + } +end diff --git a/plugins/stoa/test/functional/stoa_plugin_controller_test.rb b/plugins/stoa/test/functional/stoa_plugin_controller_test.rb index 938896a..1c503ef 100644 --- a/plugins/stoa/test/functional/stoa_plugin_controller_test.rb +++ b/plugins/stoa/test/functional/stoa_plugin_controller_test.rb @@ -54,6 +54,114 @@ class StoaPluginControllerTest < ActionController::TestCase assert_equal user.login, json_response['username'] end + should 'authenticate with usp_id' do + @request.stubs(:ssl?).returns(true) + post :authenticate, :usp_id => user.person.usp_id.to_s, :password => '123456' + + assert_nil json_response['error'] + assert_equal user.login, json_response['username'] + end + + should 'return no fields if fields requested was none' do + @request.stubs(:ssl?).returns(true) + post :authenticate, :login => user.login, :password => '123456', :fields => 'none' + + expected_response = {'ok' => true} + + assert_nil json_response['error'] + assert_equal expected_response, json_response + end + + should 'return only the essential fields if no fields requested' do + @request.stubs(:ssl?).returns(true) + post :authenticate, :login => user.login, :password => '123456' + response = json_response.clone + + assert_nil response['error'] + assert_equal true, response.delete('ok') + assert_equal user.login, response.delete('username') + assert_equal user.email, response.delete('email') + assert_equal user.person.usp_id.to_s, response.delete('nusp') + assert response.blank? + end + + should 'return only selected fields' do + @request.stubs(:ssl?).returns(true) + Person.any_instance.stubs(:f1).returns('field1') + Person.any_instance.stubs(:f2).returns('field2') + Person.any_instance.stubs(:f3).returns('field3') + @controller.stubs(:selected_fields).returns(%w[f1 f2 f3]) + + post :authenticate, :login => user.login, :password => '123456', :fields => 'special' + response = json_response.clone + + assert_equal true, response.delete('ok') + assert_equal 'field1', response.delete('f1') + assert_equal 'field2', response.delete('f2') + assert_equal 'field3', response.delete('f3') + assert response.blank? + end + + should 'not return sensitive fields that are private' do + @request.stubs(:ssl?).returns(true) + Person.any_instance.stubs(:f1).returns('field1') + Person.any_instance.stubs(:f2).returns('field2') + Person.any_instance.stubs(:f3).returns('field3') + StoaPluginController::FIELDS['special'] = %w[f1 f2 f3] + StoaPluginController::SENSITIVE = %w[f1 f2] + person = user.person + person.fields_privacy = {:f1 => 'private', :f2 => 'public', :f3 => 'public'} + person.save! + + post :authenticate, :login => user.login, :password => '123456', :fields => 'special' + + assert !json_response.keys.include?('f1') + assert json_response.keys.include?('f2') + assert json_response.keys.include?('f3') + end + + should 'return essential fields even if they are sensitive and private' do + @request.stubs(:ssl?).returns(true) + StoaPluginController::SENSITIVE = %w[email] + person = user.person + person.fields_privacy = {:email => 'private'} + person.save! + + post :authenticate, :login => user.login, :password => '123456' + + assert json_response.keys.include?('email') + end + + should 'return only essential fields when profile is private' do + @request.stubs(:ssl?).returns(true) + Person.any_instance.stubs(:f1).returns('field1') + Person.any_instance.stubs(:f2).returns('field2') + Person.any_instance.stubs(:f3).returns('field3') + StoaPluginController::FIELDS['special'] = %w[f1 f2 f3] + StoaPluginController::FIELDS['essential'] + person = user.person + person.public_profile = false + person.save! + + post :authenticate, :login => user.login, :password => '123456', :fields => 'special' + response = json_response.clone + + assert_nil response['error'] + assert_equal true, response.delete('ok') + assert_equal user.login, response.delete('username') + assert_equal user.email, response.delete('email') + assert_equal user.person.usp_id.to_s, response.delete('nusp') + assert response.blank? + end + + should 'not crash if usp_id is invalid' do + @request.stubs(:ssl?).returns(true) + assert_nothing_raised do + post :authenticate, :usp_id => 12321123, :password => '123456' + end + assert_not_nil json_response['error'] + assert_match /user/,json_response['error'] + end + should 'check valid usp id' do usp_id = '12345678' StoaPlugin::UspUser.stubs(:exists?).with(usp_id).returns(true) @@ -91,23 +199,6 @@ class StoaPluginControllerTest < ActionController::TestCase assert !json_response['exists'] end - should 'authenticate with usp_id' do - @request.stubs(:ssl?).returns(true) - post :authenticate, :usp_id => user.person.usp_id.to_s, :password => '123456' - - assert_nil json_response['error'] - assert_equal user.login, json_response['username'] - end - - should 'not crash if usp_id is invalid' do - @request.stubs(:ssl?).returns(true) - assert_nothing_raised do - post :authenticate, :usp_id => 12321123, :password => '123456' - end - assert_not_nil json_response['error'] - assert_match /user/,json_response['error'] - end - private def json_response -- libgit2 0.21.2