Ticket #11112: active_resouce_accepts_user_and_password.2.diff
| File active_resouce_accepts_user_and_password.2.diff, 15.6 kB (added by ernesto.jimenez, 7 months ago) |
|---|
-
activeresource/test/authorization_test.rb
old new 45 45 assert_equal ["", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1] 46 46 end 47 47 48 def test_authorization_header_explicitly_setting_username_and_password 49 @authenticated_conn = ActiveResource::Connection.new("http://@localhost") 50 @authenticated_conn.user = 'david' 51 @authenticated_conn.password = 'test123' 52 authorization_header = @authenticated_conn.send!(:authorization_header) 53 assert_equal @authorization_request_header['Authorization'], authorization_header['Authorization'] 54 authorization = authorization_header["Authorization"].to_s.split 55 56 assert_equal "Basic", authorization[0] 57 assert_equal ["david", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1] 58 end 59 60 def test_authorization_header_explicitly_setting_username_but_no_password 61 @conn = ActiveResource::Connection.new("http://@localhost") 62 @conn.user = "david" 63 authorization_header = @conn.send!(:authorization_header) 64 authorization = authorization_header["Authorization"].to_s.split 65 66 assert_equal "Basic", authorization[0] 67 assert_equal ["david"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1] 68 end 69 70 def test_authorization_header_explicitly_setting_password_but_no_username 71 @conn = ActiveResource::Connection.new("http://@localhost") 72 @conn.password = "test123" 73 authorization_header = @conn.send!(:authorization_header) 74 authorization = authorization_header["Authorization"].to_s.split 75 76 assert_equal "Basic", authorization[0] 77 assert_equal ["", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1] 78 end 79 48 80 def test_get 49 81 david = @authenticated_conn.get("/people/2.xml") 50 82 assert_equal "David", david["name"] -
activeresource/test/base/custom_methods_test.rb
old new 32 32 mock.put "/people/1/addresses/sort.xml?by=name", {}, nil, 204 33 33 mock.post "/people/1/addresses/new/link.xml", {}, { :street => '12345 Street' }.to_xml(:root => 'address'), 201, 'Location' => '/people/1/addresses/2.xml' 34 34 end 35 36 Person.user = nil 37 Person.password = nil 35 38 end 36 39 37 40 def teardown -
activeresource/test/base_test.rb
old new 42 42 mock.head "/people/1/addresses/2.xml", {}, nil, 404 43 43 mock.head "/people/2/addresses/1.xml", {}, nil, 404 44 44 end 45 46 Person.user = nil 47 Person.password = nil 45 48 end 46 49 47 50 … … 68 71 assert_nil actor.site 69 72 end 70 73 74 def test_should_accept_setting_user 75 Forum.user = 'david' 76 assert_equal('david', Forum.user) 77 assert_equal('david', Forum.connection.user) 78 end 79 80 def test_should_accept_setting_password 81 Forum.password = 'test123' 82 assert_equal('test123', Forum.password) 83 assert_equal('test123', Forum.connection.password) 84 end 85 86 def test_user_variable_can_be_reset 87 actor = Class.new(ActiveResource::Base) 88 actor.site = 'http://cinema' 89 assert_nil actor.user 90 actor.user = 'username' 91 actor.user = nil 92 assert_nil actor.user 93 assert_nil actor.connection.user 94 end 95 96 def test_password_variable_can_be_reset 97 actor = Class.new(ActiveResource::Base) 98 actor.site = 'http://cinema' 99 assert_nil actor.password 100 actor.password = 'username' 101 actor.password = nil 102 assert_nil actor.password 103 assert_nil actor.connection.password 104 end 105 71 106 def test_site_reader_uses_superclass_site_until_written 72 107 # Superclass is Object so returns nil. 73 108 assert_nil ActiveResource::Base.site … … 103 138 apple = Class.new(fruit) 104 139 105 140 fruit.site = 'http://market' 106 assert_equal fruit.site, apple.site, 'subclass did not adopt changes toparent class'141 assert_equal fruit.site, apple.site, 'subclass did not adopt changes from parent class' 107 142 108 143 fruit.site = 'http://supermarket' 109 assert_equal fruit.site, apple.site, 'subclass did not adopt changes toparent class'144 assert_equal fruit.site, apple.site, 'subclass did not adopt changes from parent class' 110 145 end 111 146 147 def test_user_reader_uses_superclass_user_until_written 148 # Superclass is Object so returns nil. 149 assert_nil ActiveResource::Base.user 150 assert_nil Class.new(ActiveResource::Base).user 151 Person.user = 'anonymous' 152 153 # Subclass uses superclass user. 154 actor = Class.new(Person) 155 assert_equal Person.user, actor.user 156 157 # Subclass returns frozen superclass copy. 158 assert !Person.user.frozen? 159 assert actor.user.frozen? 160 161 # Changing subclass user doesn't change superclass user. 162 actor.user = 'david' 163 assert_not_equal Person.user, actor.user 164 165 # Changing superclass user doesn't overwrite subclass user. 166 Person.user = 'john' 167 assert_not_equal Person.user, actor.user 168 169 # Changing superclass user after subclassing changes subclass user. 170 jester = Class.new(actor) 171 actor.user = 'john.doe' 172 assert_equal actor.user, jester.user 173 174 # Subclasses are always equal to superclass user when not overridden 175 fruit = Class.new(ActiveResource::Base) 176 apple = Class.new(fruit) 177 178 fruit.user = 'manager' 179 assert_equal fruit.user, apple.user, 'subclass did not adopt changes from parent class' 180 181 fruit.user = 'client' 182 assert_equal fruit.user, apple.user, 'subclass did not adopt changes from parent class' 183 end 184 185 def test_password_reader_uses_superclass_password_until_written 186 # Superclass is Object so returns nil. 187 assert_nil ActiveResource::Base.password 188 assert_nil Class.new(ActiveResource::Base).password 189 Person.password = 'my-password' 190 191 # Subclass uses superclass password. 192 actor = Class.new(Person) 193 assert_equal Person.password, actor.password 194 195 # Subclass returns frozen superclass copy. 196 assert !Person.password.frozen? 197 assert actor.password.frozen? 198 199 # Changing subclass password doesn't change superclass password. 200 actor.password = 'secret' 201 assert_not_equal Person.password, actor.password 202 203 # Changing superclass password doesn't overwrite subclass password. 204 Person.password = 'super-secret' 205 assert_not_equal Person.password, actor.password 206 207 # Changing superclass password after subclassing changes subclass password. 208 jester = Class.new(actor) 209 actor.password = 'even-more-secret' 210 assert_equal actor.password, jester.password 211 212 # Subclasses are always equal to superclass password when not overridden 213 fruit = Class.new(ActiveResource::Base) 214 apple = Class.new(fruit) 215 216 fruit.password = 'mega-secret' 217 assert_equal fruit.password, apple.password, 'subclass did not adopt changes from parent class' 218 219 fruit.password = 'ok-password' 220 assert_equal fruit.password, apple.password, 'subclass did not adopt changes from parent class' 221 end 222 112 223 def test_updating_baseclass_site_object_wipes_descendent_cached_connection_objects 113 224 # Subclasses are always equal to superclass site when not overridden 114 225 fruit = Class.new(ActiveResource::Base) … … 116 227 117 228 fruit.site = 'http://market' 118 229 assert_equal fruit.connection.site, apple.connection.site 230 first_connection = apple.connection.object_id 119 231 120 232 fruit.site = 'http://supermarket' 121 assert_equal fruit.connection.site, apple.connection.site 233 assert_equal fruit.connection.site, apple.connection.site 234 second_connection = apple.connection.object_id 235 assert_not_equal(first_connection, second_connection, 'Connection should be re-created') 122 236 end 123 237 238 def test_updating_baseclass_user_wipes_descendent_cached_connection_objects 239 # Subclasses are always equal to superclass user when not overridden 240 fruit = Class.new(ActiveResource::Base) 241 apple = Class.new(fruit) 242 fruit.site = 'http://market' 243 244 fruit.user = 'david' 245 assert_equal fruit.connection.user, apple.connection.user 246 first_connection = apple.connection.object_id 247 248 fruit.user = 'john' 249 assert_equal fruit.connection.user, apple.connection.user 250 second_connection = apple.connection.object_id 251 assert_not_equal(first_connection, second_connection, 'Connection should be re-created') 252 end 253 254 def test_updating_baseclass_password_wipes_descendent_cached_connection_objects 255 # Subclasses are always equal to superclass password when not overridden 256 fruit = Class.new(ActiveResource::Base) 257 apple = Class.new(fruit) 258 fruit.site = 'http://market' 259 260 fruit.password = 'secret' 261 assert_equal fruit.connection.password, apple.connection.password 262 first_connection = apple.connection.object_id 263 264 fruit.password = 'supersecret' 265 assert_equal fruit.connection.password, apple.connection.password 266 second_connection = apple.connection.object_id 267 assert_not_equal(first_connection, second_connection, 'Connection should be re-created') 268 end 269 124 270 def test_collection_name 125 271 assert_equal "people", Person.collection_name 126 272 end -
activeresource/lib/active_resource/connection.rb
old new 55 55 # This class is used by ActiveResource::Base to interface with REST 56 56 # services. 57 57 class Connection 58 attr_reader :site 58 attr_reader :site, :user, :password 59 59 attr_accessor :format 60 60 61 61 class << self … … 68 68 # attribute to the URI for the remote resource service. 69 69 def initialize(site, format = ActiveResource::Formats[:xml]) 70 70 raise ArgumentError, 'Missing site URI' unless site 71 @user = @password = nil 71 72 self.site = site 72 73 self.format = format 73 74 end … … 75 76 # Set URI for remote service. 76 77 def site=(site) 77 78 @site = site.is_a?(URI) ? site : URI.parse(site) 79 @user = @site.user if @site.user 80 @password = @site.password if @site.password 78 81 end 79 82 83 # Set user for remote service. 84 def user=(user) 85 @user = user 86 end 87 88 # Set password for remote service. 89 def password=(password) 90 @password = password 91 end 92 80 93 # Execute a GET request. 81 94 # Used to get (find) resources. 82 95 def get(path, headers = {}) … … 166 179 authorization_header.update(default_header).update(headers) 167 180 end 168 181 169 # Sets authorization header ; authentication information is pulled from credentials provided with site URI.182 # Sets authorization header 170 183 def authorization_header 171 (@ site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})184 (@user || @password ? { 'Authorization' => 'Basic ' + ["#{@user}:#{ @password}"].pack('m').delete("\r\n") } : {}) 172 185 end 173 186 174 187 def logger #:nodoc: -
activeresource/lib/active_resource/base.rb
old new 85 85 # == Authentication 86 86 # 87 87 # Many REST APIs will require authentication, usually in the form of basic 88 # HTTP authentication. Authentication can be specified by putting the credentials89 # in the +site+ variable of the Active Resource class you need to authenticate.88 # HTTP authentication. Authentication can be specified by: 89 # * putting the credentials in the +site+ variable. 90 90 # 91 # class Person < ActiveResource::Base92 # self.site = "http://ryan:password@api.people.com:3000/"93 # end91 # class Person < ActiveResource::Base 92 # self.site = "http://ryan:password@api.people.com:3000/" 93 # end 94 94 # 95 # * defining +user+ and/or +password+ variables 96 # 97 # class Person < ActiveResource::Base 98 # self.site = "http://api.people.com:3000/" 99 # self.user = "ryan" 100 # self.password = "password" 101 # end 102 # 95 103 # For obvious security reasons, it is probably best if such services are available 96 104 # over HTTPS. 97 105 # 106 # Note: when specified in the +site+ variable, credentials such as email are not accepted 107 # because of restrictions from URI library. 108 # 98 109 # == Errors & Validation 99 110 # 100 111 # Error handling and validation is handled in much the same manner as you're used to seeing in … … 164 175 # Gets the URI of the REST resources to map for this class. The site variable is required 165 176 # ActiveResource's mapping to work. 166 177 def site 178 # Not using superclass_delegating_reader because don't want subclasses to modify superclass instance 179 # 180 # With superclass_delegating_reader 181 # 182 # Parent.site = 'http://anonymous@test.com' 183 # Subclass.site # => 'http://anonymous@test.com' 184 # Subclass.site.user = 'david' 185 # Parent.site # => 'http://david@test.com' 186 # 187 # Without superclass_delegating_reader (expected behaviour) 188 # 189 # Parent.site = 'http://anonymous@test.com' 190 # Subclass.site # => 'http://anonymous@test.com' 191 # Subclass.site.user = 'david' # => TypeError: can't modify frozen object 192 # 167 193 if defined?(@site) 168 194 @site 169 195 elsif superclass != Object && superclass.site … … 175 201 # The site variable is required ActiveResource's mapping to work. 176 202 def site=(site) 177 203 @connection = nil 178 @site = site.nil? ? nil : create_site_uri_from(site) 204 if site.nil? 205 @site = nil 206 else 207 @site = create_site_uri_from(site) 208 @user = @site.user if @site.user 209 @password = @site.password if @site.password 210 end 179 211 end 180 212 213 # Gets the user for REST HTTP authentication 214 def user 215 # Not using superclass_delegating_reader. See +site+ for explanation 216 if defined?(@user) 217 @user 218 elsif superclass != Object && superclass.user 219 superclass.user.dup.freeze 220 end 221 end 222 223 # Sets the user for REST HTTP authentication 224 def user=(user) 225 @connection = nil 226 @user = user 227 end 228 229 # Gets the password for REST HTTP authentication 230 def password 231 # Not using superclass_delegating_reader. See +site+ for explanation 232 if defined?(@password) 233 @password 234 elsif superclass != Object && superclass.password 235 superclass.password.dup.freeze 236 end 237 end 238 239 # Sets the password for REST HTTP authentication 240 def password=(password) 241 @connection = nil 242 @password = password 243 end 244 181 245 # Sets the format that attributes are sent and received in from a mime type reference. Example: 182 246 # 183 247 # Person.format = :json … … 206 270 def connection(refresh = false) 207 271 if defined?(@connection) || superclass == Object 208 272 @connection = Connection.new(site, format) if refresh || @connection.nil? 273 @connection.user = user if user 274 @connection.password = password if password 209 275 @connection 210 276 else 211 277 superclass.connection