jenkins-bot has submitted this change and it was merged.

Change subject: Fix infinite recursion during login
......................................................................


Fix infinite recursion during login

The `Client#log_in` method recurses when the API returns a `NeedToken`
response. To prevent infinite recursion in edge cases, where the
subsequent request might not sufficiently authenticate using the
returned token, an exception is now raised after a second request.

Bug: T111133
Change-Id: Ia7b88ce2822a052ef28c7256660270efe23e4df0
---
M lib/mediawiki_api/client.rb
M spec/client_spec.rb
M spec/support/request_helpers.rb
3 files changed, 40 insertions(+), 24 deletions(-)

Approvals:
  Zfilipin: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/lib/mediawiki_api/client.rb b/lib/mediawiki_api/client.rb
index 876ee52..5a4d80d 100644
--- a/lib/mediawiki_api/client.rb
+++ b/lib/mediawiki_api/client.rb
@@ -93,6 +93,7 @@
         @logged_in = true
         @tokens.clear
       when 'NeedToken'
+        raise LoginError, "failed to log in with the returned token 
'#{token}'" unless token.nil?
         data = log_in(username, password, data['token'])
       else
         raise LoginError, data['result']
diff --git a/spec/client_spec.rb b/spec/client_spec.rb
index dd1678a..64aaf21 100644
--- a/spec/client_spec.rb
+++ b/spec/client_spec.rb
@@ -194,7 +194,6 @@
   end
 
   describe '#log_in' do
-
     it 'logs in when API returns Success' do
       stub_request(:post, api_url).
         with(body: { format: 'json', action: 'login', lgname: 'Test', 
lgpassword: 'qwe123' }).
@@ -205,39 +204,48 @@
     end
 
     context 'when API returns NeedToken' do
-      before do
-        stub_request(:post, api_url).
-          with(body: { format: 'json', action: 'login', lgname: 'Test', 
lgpassword: 'qwe123' }).
-          to_return(
-            body: { login: body_base.merge(result: 'NeedToken', token: '456') 
}.to_json,
-            headers: { 'Set-Cookie' => 'prefixSession=789; path=/; 
domain=localhost; HttpOnly' }
-          )
+      context 'and a token was not given' do
+        before do
+          stub_login_request('Test', 'qwe123').
+            to_return(
+              body: { login: body_base.merge(result: 'NeedToken', token: 
'456') }.to_json,
+              headers: { 'Set-Cookie' => 'prefixSession=789; path=/; 
domain=localhost; HttpOnly' }
+            )
 
-        @success_req = stub_request(:post, api_url).
-          with(body: { format: 'json', action: 'login',
-                       lgname: 'Test', lgpassword: 'qwe123', lgtoken: '456' }).
-          with(headers: { 'Cookie' => 'prefixSession=789' }).
-          to_return(body: { login: body_base.merge(result: 'Success') 
}.to_json)
+          @success_req = stub_login_request('Test', 'qwe123', '456').
+            with(headers: { 'Cookie' => 'prefixSession=789' }).
+            to_return(body: { login: body_base.merge(result: 'Success') 
}.to_json)
+        end
+
+        it 'logs in' do
+          response = subject.log_in('Test', 'qwe123')
+
+          expect(response).to include('result' => 'Success')
+          expect(subject.logged_in).to be true
+        end
+
+        it 'sends second request with token and cookies' do
+          subject.log_in('Test', 'qwe123')
+
+          expect(@success_req).to have_been_requested
+        end
       end
 
-      it 'logs in' do
-        response = subject.log_in('Test', 'qwe123')
+      context 'but a token was already provided' do
+        subject { client.log_in('Test', 'qwe123', '123') }
 
-        expect(response).to include('result' => 'Success')
-        expect(subject.logged_in).to be true
-      end
+        it 'should raise a LoginError' do
+          stub_login_request('Test', 'qwe123', '123').
+            to_return(body: { login: body_base.merge(result: 'NeedToken', 
token: '456') }.to_json)
 
-      it 'sends second request with token and cookies' do
-        subject.log_in('Test', 'qwe123')
-
-        expect(@success_req).to have_been_requested
+          expect { subject }.to raise_error(MediawikiApi::LoginError)
+        end
       end
     end
 
     context 'when API returns neither Success nor NeedToken' do
       before do
-        stub_request(:post, api_url).
-          with(body: { format: 'json', action: 'login', lgname: 'Test', 
lgpassword: 'qwe123' }).
+        stub_login_request('Test', 'qwe123').
           to_return(body: { login: body_base.merge(result: 'EmptyPass') 
}.to_json)
       end
 
diff --git a/spec/support/request_helpers.rb b/spec/support/request_helpers.rb
index 074a024..d1cecb5 100644
--- a/spec/support/request_helpers.rb
+++ b/spec/support/request_helpers.rb
@@ -26,6 +26,13 @@
       stub_api_request(method, params.merge(action: action, token: mock_token))
     end
 
+    def stub_login_request(username, password, token = nil)
+      params = { action: 'login', lgname: username, lgpassword: password }
+      params[:lgtoken] = token unless token.nil?
+
+      stub_api_request(:post, params)
+    end
+
     def stub_token_request(type, warning = nil)
       response = { query: { tokens: { "#{type}token" => mock_token } } }
       response[:warnings] = { type => { '*' => [warning] } } unless 
warning.nil?

-- 
To view, visit https://gerrit.wikimedia.org/r/235388
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ia7b88ce2822a052ef28c7256660270efe23e4df0
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/ruby/api
Gerrit-Branch: master
Gerrit-Owner: Dduvall <[email protected]>
Gerrit-Reviewer: Hashar <[email protected]>
Gerrit-Reviewer: Robmoen <[email protected]>
Gerrit-Reviewer: Zfilipin <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to