CSteipp has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/74543


Change subject: Adding re-authorize flow
......................................................................

Adding re-authorize flow

Re-authorization form is ugly, and probably needs some UX help, but
the basic functionality is there.

Change-Id: Ia40cea2ad2346c514e6bf661d4ba6efc07caebe9
---
M backend/MWOAuthConsumerAcceptance.php
M backend/MWOAuthDataStore.php
M backend/MWOAuthServer.php
M frontend/language/MWOAuth.i18n.php
M frontend/specialpages/SpecialMWOAuth.php
M tests/testClient.php
M tests/testClientHeaders.php
7 files changed, 116 insertions(+), 25 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/OAuth 
refs/changes/43/74543/1

diff --git a/backend/MWOAuthConsumerAcceptance.php 
b/backend/MWOAuthConsumerAcceptance.php
index f370ef0..fc295d4 100644
--- a/backend/MWOAuthConsumerAcceptance.php
+++ b/backend/MWOAuthConsumerAcceptance.php
@@ -82,6 +82,32 @@
                }
        }
 
+       /**
+        * @param DBConnRef $db
+        * @param User $user user who authorized
+        * @param MWOAuthConsumer $consumer
+        * @param integer $flags MWOAuthConsumerAcceptance::READ_* bitfield
+        * @return MWOAuthConsumerAcceptance|bool
+        */
+       public static function newFromUserConsumer( DBConnRef $db, $user, 
$consumer, $flags = 0 ) {
+               $row = $db->selectRow( static::getTable(),
+                       array_values( static::getFieldColumnMap() ),
+                       array( 'oaac_user_id' => $user->getId(),
+                               'oaac_consumer_id' => $consumer->get( 'id' )
+                       ),
+                       __METHOD__,
+                       ( $flags & self::READ_LOCKING ) ? array( 'FOR UPDATE' ) 
: array()
+               );
+
+               if ( $row ) {
+                       $consumer = new self();
+                       $consumer->loadFromRow( $db, $row );
+                       return $consumer;
+               } else {
+                       return false;
+               }
+       }
+
        protected function normalizeValues() {
                $this->userId = (int)$this->userId;
                $this->consumerId = (int)$this->consumerId;
diff --git a/backend/MWOAuthDataStore.php b/backend/MWOAuthDataStore.php
index d111b6f..421e126 100644
--- a/backend/MWOAuthDataStore.php
+++ b/backend/MWOAuthDataStore.php
@@ -136,7 +136,12 @@
                }
 
                $accessToken = $this->lookup_token( $consumer, 'access', 
$token->getAccessKey() );
-               $this->cache->delete( MWOAuthUtils::getCacheKey( 'token', 
$consumer->get( 'consumerKey' ), 'request', $token->key ) );
+               $this->cache->delete( MWOAuthUtils::getCacheKey(
+                       'token',
+                       $consumer->key,
+                       'request',
+                       $token->key
+               ) );
                wfDebugLog( 'OAuth', __METHOD__ . ": New access token 
{$accessToken->key} for {$consumer->key}" );
                return $accessToken;
        }
diff --git a/backend/MWOAuthServer.php b/backend/MWOAuthServer.php
index 73ed605..5dbab40 100644
--- a/backend/MWOAuthServer.php
+++ b/backend/MWOAuthServer.php
@@ -89,9 +89,10 @@
         * @param String $consumerKey
         * @param String $requestTokenKey
         * @param User $mwUser user authorizing the request
+        * @param bool $update update the grants/wiki to those requested by 
consumer
         * @return String the callback URL to redirect the user
         */
-       public function authorize( $consumerKey, $requestTokenKey, $mwUser ) {
+       public function authorize( $consumerKey, $requestTokenKey, $mwUser, 
$update ) {
 
                // Check that user and consumer are in good standing
                // TODO: Anything else? mwoauthmanagemyconsumers?
@@ -108,37 +109,65 @@
                }
 
                // Generate and Update the tokens:
-               // * Generate Access token, and add a pointer to it in the 
request token
                // * Generate a new Verification code, and add it to the 
request token
-               // * Resave Request token with 
-               $accessToken = MWOAuthDataStore::newToken();
+               // * Either add or update the authorization
+               // ** Generate a new access token if this is a new authorization
+               // * Resave request token with the access token
+
                $verifyCode = MWCryptRand::generateHex( 32, true);
                $requestToken = $this->data_store->lookup_token( $consumer, 
'request', $requestTokenKey );
                if ( !$requestToken || !( $requestToken instanceof MWOAuthToken 
) ) {
                        throw new MWOAuthException( 
'mwoauthserver-invalid-request-token' );
                }
                $requestToken->addVerifyCode( $verifyCode );
-               $requestToken->addAccessKey( $accessToken->key );
-               $this->data_store->updateRequestToken( $requestToken, $consumer 
);
 
                // Make sure other extensions can switch out our user. 
CentralAuth may abort here
                // if there is no global account for this user.
                $this->getOAuthUser( $mwUser );
 
-               // Add the Authorization to the database
-               $cmra = MWOAuthConsumerAcceptance::newFromArray( array(
-                       'wiki'         => $consumer->get( 'wiki' ),
-                       'userId'       => $mwUser->getId(),
-                       'consumerId'   => $consumer->get( 'id' ),
-                       'accessToken'  => $accessToken->key,
-                       'accessSecret' => $accessToken->secret,
-                       'grants'       => $consumer->get( 'grants' ),
-                       'accepted'     => wfTimestampNow()
-               ) );
-               $cmra->save( MWOAuthUtils::getCentralDB( DB_MASTER ) );
+               // Authorization Token
+               $dbw = MWOAuthUtils::getCentralDB( DB_MASTER );
 
+               // Check if this authorization exists
+               $cmra = MWOAuthConsumerAcceptance::newFromUserConsumer(
+                       $dbw,
+                       $mwUser,
+                       $consumer
+               );
+
+               if ( $update ) {
+                       // This should be an update to an existing authorization
+                       if ( !$cmra ) {
+                               // update requested, but no existing key
+                               throw new MWOAuthException( 
'mwoauthserver-invalid-request' );
+                       }
+                       $cmra->setFields( array(
+                               'wiki'   => $consumer->get( 'wiki' ),
+                               'grants' => $consumer->get( 'grants' )
+                       ) );
+                       $cmra->save( $dbw );
+                       $accessToken = new MWOAuthToken( $cmra->get( 
'accessToken' ), '' );
+               } elseif ( !$cmra ) {
+                       // Add the Authorization to the database
+                       $accessToken = MWOAuthDataStore::newToken();
+                       $cmra = MWOAuthConsumerAcceptance::newFromArray( array(
+                               'wiki'         => $consumer->get( 'wiki' ),
+                               'userId'       => $mwUser->getId(),
+                               'consumerId'   => $consumer->get( 'id' ),
+                               'accessToken'  => $accessToken->key,
+                               'accessSecret' => $accessToken->secret,
+                               'grants'       => $consumer->get( 'grants' ),
+                               'accepted'     => wfTimestampNow()
+                       ) );
+                       $cmra->save( MWOAuthUtils::getCentralDB( DB_MASTER ) );
+               } else {
+                       // Authorization exists, no updates requested, so no 
changes to the db
+                       $accessToken = new MWOAuthToken( $cmra->get( 
'accessToken' ), '' );
+               }
+
+               $requestToken->addAccessKey( $accessToken->key );
+               $this->data_store->updateRequestToken( $requestToken, $consumer 
);
                wfDebugLog( 'OAuth', "Verification code 
{$requestToken->getVerifyCode()} for $requestTokenKey (client: $consumerKey)" );
-
                return $consumer->generateCallbackUrl( 
$requestToken->getVerifyCode(), $requestTokenKey );
        }
 
diff --git a/frontend/language/MWOAuth.i18n.php 
b/frontend/language/MWOAuth.i18n.php
index b6afefe..0915e5e 100644
--- a/frontend/language/MWOAuth.i18n.php
+++ b/frontend/language/MWOAuth.i18n.php
@@ -184,9 +184,14 @@
        'mwoauthserver-invalid-user-hookabort' => 'This user cannot use OAuth',
 
        'mwoauth-form-description' => 'The following application is requesting 
to use MediaWiki on your behalf. The application will be able to perform any 
actions that are allowed with the list if reqested rights below. Only allow 
applications that you trust to use these permissions as you would.',
+       'mwoauth-form-existing' => "'''This application is requesting 
authorization to MediaWiki on your behalf, but you have already granted 
access:'''
+*  Grants: $1
+*  Wiki: $2
+*  Authorized on: $3",
        'mwoauth-form-legal' => '',
        'mwoauth-form-button-approve' => 'Yes, allow',
        'mwoauth-form-confirmation' => 'Allow this application to act on your 
behalf?',
+       'mwoauth-form-confirmation-update' => 'Update this authorization to the 
requested privileges. Leaving this unchecked will keep your existing 
authorizations',
        'mwoauth-authorize-form' => 'Application details:',
        'mwoauth-authorize-form-user' => 'Application author: $1',
        'mwoauth-authorize-form-name' => 'Application name: $1',
diff --git a/frontend/specialpages/SpecialMWOAuth.php 
b/frontend/specialpages/SpecialMWOAuth.php
index b511cb4..524d2d1 100644
--- a/frontend/specialpages/SpecialMWOAuth.php
+++ b/frontend/specialpages/SpecialMWOAuth.php
@@ -19,6 +19,7 @@
                        $oauthServer = new MWOAuthServer( $store );
                        $oauthServer->add_signature_method( new 
OAuthSignatureMethod_HMAC_SHA1() );
                        $oauthServer->add_signature_method( new 
MWOAuthSignatureMethod_RSA_SHA1( $store ) );
+                       //TODO: user MWOAuthUtils::getServer()
 
                        switch ( $subpage ) {
                                case 'initiate':
@@ -29,6 +30,7 @@
                                        $this->returnToken( $token, $format );
                                        break;
                                case 'authorize':
+                                       //TODO: most of the "controller" logic 
should be move somewhere else
                                        $mwUser = $this->getUser();
                                        $requestToken = $request->getVal( 
'oauth_token', false ); //oauth_token
                                        $consumerKey = $request->getVal( 
'oauth_consumer_key', false ); //oauth_key
@@ -65,22 +67,32 @@
                                                $callback = 
$oauthServer->authorize(
                                                        $consumerKey,
                                                        $requestToken,
-                                                       $mwUser
+                                                       $mwUser,
+                                                       $request->getCheck( 
'grants-update' )
                                                );
                                                // Redirect to callback url
                                                $this->doRedirect( $callback );
                                        } else {
+                                               $dbr = 
MWOAuthUtils::getCentralDB( DB_SLAVE );
                                                $consumer = 
MWOAuthDAOAccessControl::wrap(
-                                                               
MWOAuthConsumer::newFromKey( MWOAuthUtils::getCentralDB( DB_SLAVE ), 
$consumerKey ),
+                                                               
MWOAuthConsumer::newFromKey( $dbr, $consumerKey ),
                                                                
$this->getContext()
                                                );
                                                if ( !$consumer ) {
                                                        throw new 
MWOAuthException( 'mwoauth-bad-request' );
                                                }
+                                               // Check if this user has 
authorized grants for this consumer previously
+                                               $existing = 
MWOAuthConsumerAcceptance::newFromUserConsumer(
+                                                       $dbr,
+                                                       $mwUser,
+                                                       
MWOAuthConsumer::newFromKey( $dbr, $consumerKey )
+                                               );
+
                                                $formParams = array(
                                                        'consumerKey' => 
$consumerKey,
                                                        'requestToken' => 
$requestToken,
                                                        'grants' => 
$consumer->get( 'grants' ),
+                                                       'existing' => $existing,
                                                        'description' => array (
                                                                'user' => 
User::newFromId( $consumer->get( 'userId') )->getName(),
                                                                'name' => 
$consumer->get( 'name'),
@@ -127,7 +139,18 @@
                $user = $this->getUser();
 
                $out->addSubtitle( $this->msg( 'mwoauth-desc' )->escaped() );
-               $out->addHTML( Html::element( 'p', array(), $this->msg( 
'mwoauth-form-description' )->text() ) );
+               if ( !$params['existing'] ) {
+                       $out->addHTML( Html::element( 'p', array(), $this->msg( 
'mwoauth-form-description' )->text() ) );
+               } else {
+                       // User has already authorized this consumer
+                       $lang = $this->getLanguage();
+                       $grants = $params['existing']->get( 'grants');
+                       $grantList = is_null( $grants ) ? $this->msg( 
'mwoauth-grants-nogrants' )->text() : $lang->commaList( $grants );
+                       $out->addWikiMsg( 'mwoauth-form-existing',
+                               $grantList,
+                               $params['existing']->get( 'wiki'),
+                               $params['existing']->get( 'accepted' ) );
+               }
                $out->addHTML( Html::element( 'p', array(), $this->msg( 
'mwoauth-form-legal' )->text() ) );
 
                $out->addHTML( Html::element( 'p', array(), $this->msg( 
'mwoauth-authorize-form' )->text() ) );
@@ -148,7 +171,10 @@
                $out->addHTML( Html::rawElement( 'ul', array(), $description ) 
);
 
                $out->addHTML( $this->getGrantsHtml( $params['grants'] ) );
-
+               if ( $params['existing'] ) {
+                       // Checkbox to allow the user to update their 
permission to match the Consumer's request
+                       $fields['mwoauth-form-confirmation-update'] = 
Xml::check( 'grants-update', false );
+               }
                $fields['mwoauth-form-confirmation'] = Xml::submitButton( 
$this->msg( 'mwoauth-form-button-approve' )->text() );
                $form = Xml::buildForm( $fields );
                $form = Xml::fieldset( null, $form );
diff --git a/tests/testClient.php b/tests/testClient.php
index 6820b20..bd3b1ae 100644
--- a/tests/testClient.php
+++ b/tests/testClient.php
@@ -12,7 +12,7 @@
 
 $consumerKey = 'dpf43f3p2l4k3l03';
 $consumerSecret = 'kd94hf93k423kf44';
-$baseurl = 'https://localhost/wiki/index.php?title=Special:OAuth';
+$baseurl = 'https://localhost/wiki/index.php?title=Special:MWOAuth';
 $endpoint = $baseurl . '/initiate&format=json';
 
 $endpoint_acc = $baseurl . '/token&format=json';
diff --git a/tests/testClientHeaders.php b/tests/testClientHeaders.php
index 920ad2a..82c8a19 100644
--- a/tests/testClientHeaders.php
+++ b/tests/testClientHeaders.php
@@ -12,7 +12,7 @@
 
 $consumerKey = 'dpf43f3p2l4k3l03';
 $consumerSecret = 'kd94hf93k423kf44';
-$baseurl = 'https://localhost/wiki/index.php?title=Special:OAuth';
+$baseurl = 'https://localhost/wiki/index.php?title=Special:MWOAuth';
 $endpoint = $baseurl . '/initiate&format=json';
 
 $endpoint_acc = $baseurl . '/token&format=json';

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia40cea2ad2346c514e6bf661d4ba6efc07caebe9
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/OAuth
Gerrit-Branch: master
Gerrit-Owner: CSteipp <[email protected]>

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

Reply via email to