Aaron Schulz has uploaded a new change for review.
https://gerrit.wikimedia.org/r/72990
Change subject: Added Special:MWOAuthManageMyGrants page
......................................................................
Added Special:MWOAuthManageMyGrants page
* Various small cleanups
Change-Id: I669bd4b750cdfafd18dad60d8cdabdc1675113f4
---
M OAuth.config.php
M OAuth.setup.php
M backend/MWOAuthConsumer.php
M backend/MWOAuthDAO.php
M control/MWOAuthConsumerSubmitControl.php
M control/MWOAuthDAOAccessControl.php
M control/MWOAuthSubmitControl.php
M frontend/MWOAuthUI.setup.php
M frontend/language/MWOAuth.i18n.php
M frontend/specialpages/actions/MWOAuthManageConsumers.php
10 files changed, 100 insertions(+), 84 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/OAuth
refs/changes/90/72990/1
diff --git a/OAuth.config.php b/OAuth.config.php
index 36a9ff6..fc4e9d0 100644
--- a/OAuth.config.php
+++ b/OAuth.config.php
@@ -12,6 +12,7 @@
$wgAvailableRights[] = 'mwoauthsuppress';
$wgAvailableRights[] = 'mwoauthviewsuppressed';
$wgAvailableRights[] = 'mwoauthviewprivate';
+$wgAvailableRights[] = 'mwoauthmanagemyconsumers';
# End of configuration variables.
# ########
diff --git a/OAuth.setup.php b/OAuth.setup.php
index 6714af5..8b30872 100644
--- a/OAuth.setup.php
+++ b/OAuth.setup.php
@@ -35,6 +35,7 @@
$classes['MWOAuthConsumerRegistration'] =
"$spActionDir/MWOAuthConsumerRegistration.php";
$classes['MWOAuthManageConsumers'] =
"$spActionDir/MWOAuthManageConsumers.php";
+ $classes['MWOAuthManageMyGrants'] =
"$spActionDir/MWOAuthManageMyGrants.php";
# Special:MWOAuth/authorize
# Special:MWOAuth/initiate?
# Special:MWOAuth/token?
@@ -45,11 +46,14 @@
# Data access objects
$classes['MWOAuthDAO'] = "$backendDir/MWOAuthDAO.php";
$classes['MWOAuthConsumer'] = "$backendDir/MWOAuthConsumer.php";
+ $classes['MWOAuthConsumerAcceptance'] =
"$backendDir/MWOAuthConsumerAcceptance.php";
# Control logic
$classes['MWOAuthDAOAccessControl'] =
"$controlDir/MWOAuthDAOAccessControl.php";
$classes['MWOAuthSubmitControl'] =
"$controlDir/MWOAuthSubmitControl.php";
$classes['MWOAuthConsumerSubmitControl'] =
"$controlDir/MWOAuthConsumerSubmitControl.php";
+ $classes['MWOAuthConsumerAcceptanceSubmitControl'] =
+
"$controlDir/MWOAuthConsumerAcceptanceSubmitControl.php";
# Schema changes
$classes['MWOAuthUpdaterHooks'] =
"$schemaDir/MWOAuthUpdater.hooks.php";
diff --git a/backend/MWOAuthConsumer.php b/backend/MWOAuthConsumer.php
index d18e6f4..c6066e9 100644
--- a/backend/MWOAuthConsumer.php
+++ b/backend/MWOAuthConsumer.php
@@ -26,7 +26,7 @@
protected $id;
/** @var string Hex token */
protected $consumerKey;
- /** @var integer Publisher user ID */
+ /** @var integer Publisher user ID (on central wiki) */
protected $userId;
/** @var string Version used for handshake breaking changes */
protected $version;
@@ -46,6 +46,8 @@
protected $secretKey;
/** @var string RSA key */
protected $rsaKey;
+ /** @var array List of grants */
+ protected $grants;
/** @var array IP restrictions */
protected $restrictions;
/** @var integer MWOAuthConsumer::STAGE_* constant */
@@ -182,7 +184,8 @@
$row['oarc_stage_timestamp'] = $db->timestamp(
$row['oarc_stage_timestamp'] );
$row['oarc_restrictions'] = FormatJSON::encode(
$row['oarc_restrictions'] );
$row['oarc_grants'] = FormatJSON::encode( $row['oarc_grants'] );
- $row['oarc_email_authenticated'] = $db->timestamp(
$row['oarc_email_authenticated'] );
+ $row['oarc_email_authenticated'] =
+ $db->timestampOrNull( $row['oarc_email_authenticated']
);
return $row;
}
@@ -191,7 +194,8 @@
$row['oarc_stage_timestamp'] = wfTimestamp( TS_MW,
$row['oarc_stage_timestamp'] );
$row['oarc_restrictions'] = FormatJSON::decode(
$row['oarc_restrictions'], true );
$row['oarc_grants'] = FormatJSON::decode( $row['oarc_grants'],
true );
- $row['oarc_email_authenticated'] = wfTimestamp( TS_MW,
$row['oarc_email_authenticated'] );
+ $row['oarc_email_authenticated'] =
+ wfTimestampOrNull( TS_MW,
$row['oarc_email_authenticated'] );
return $row;
}
diff --git a/backend/MWOAuthDAO.php b/backend/MWOAuthDAO.php
index a9113e1..dfb0aeb 100644
--- a/backend/MWOAuthDAO.php
+++ b/backend/MWOAuthDAO.php
@@ -22,6 +22,8 @@
* Representation of a Data Access Object
*/
abstract class MWOAuthDAO implements IDBAccessObject {
+ private $daoOrigin = 'new'; // string; object construction origin
+
/**
* @throws Exception
*/
@@ -138,7 +140,7 @@
public function save( DatabaseBase $dbw ) {
$uniqueId = $this->getIdValue();
$idColumn = static::getIdColumn();
- if ( $uniqueId ) {
+ if ( $this->daoOrigin === 'db' ) {
$dbw->update(
static::getTable(),
$this->getRowArray( $dbw ),
@@ -314,6 +316,7 @@
$values[$field] = $row[$column];
}
$this->loadFromValues( $values );
+ $this->daoOrigin = 'db';
}
/**
diff --git a/control/MWOAuthConsumerSubmitControl.php
b/control/MWOAuthConsumerSubmitControl.php
index b721203..8eae118 100644
--- a/control/MWOAuthConsumerSubmitControl.php
+++ b/control/MWOAuthConsumerSubmitControl.php
@@ -19,14 +19,13 @@
*/
/**
- * Handle the logic of submitting a application consumer request
+ * This handles the core logic of approving/disabling consumers
+ * from using particular user accounts
*
* @TODO: improve error messages
*/
class MWOAuthConsumerSubmitControl extends MWOAuthSubmitControl {
- protected function getRequiredFields() {
- return array(
- // @TODO: handle input trimming
+ protected function getRequiredFields() {return array(
// Proposer (application administrator) actions:
'propose' => array(
'name' => '/^.{1,128}$/',
@@ -137,16 +136,9 @@
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['description'] );
$logEntry->setParameters( array( '4:consumer' =>
$cmr->get( 'consumerKey' ) ) );
- $logid = $logEntry->insert( $dbw );
- // @TODO: Core wrapper
- $dbw->insert( 'log_search',
- array(
- 'ls_field' => 'OAuthConsumer',
- 'ls_value' => $cmr->get( 'consumerKey'
),
- 'ls_log_id' => $logid ),
- __METHOD__,
- 'IGNORE'
- );
+ $logEntry->setRelations( array(
+ 'OAuthConsumer' => array( $cmr->get(
'consumerKey' ) )
+ ) );
return $this->success( $cmr );
case 'update':
@@ -178,16 +170,10 @@
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['reason'] );
$logEntry->setParameters( array( '4:consumer' =>
$cmr->get( 'consumerKey' ) ) );
+ $logEntry->setRelations( array(
+ 'OAuthConsumer' => array( $cmr->get(
'consumerKey' ) )
+ ) );
$logid = $logEntry->insert( $dbw );
- // @TODO: Core wrapper
- $dbw->insert( 'log_search',
- array(
- 'ls_field' => 'OAuthConsumer',
- 'ls_value' => $cmr->get( 'consumerKey'
),
- 'ls_log_id' => $logid ),
- __METHOD__,
- 'IGNORE'
- );
return $this->success( $cmr );
case 'approve':
@@ -219,16 +205,10 @@
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['reason'] );
$logEntry->setParameters( array( '4:consumer' =>
$cmr->get( 'consumerKey' ) ) );
+ $logEntry->setRelations( array(
+ 'OAuthConsumer' => array( $cmr->get(
'consumerKey' ) )
+ ) );
$logid = $logEntry->insert( $dbw );
- // @TODO: Core wrapper
- $dbw->insert( 'log_search',
- array(
- 'ls_field' => 'OAuthConsumer',
- 'ls_value' => $cmr->get( 'consumerKey'
),
- 'ls_log_id' => $logid ),
- __METHOD__,
- 'IGNORE'
- );
// @TODO: email/notifications?
@@ -258,16 +238,10 @@
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['reason'] );
$logEntry->setParameters( array( '4:consumer' =>
$cmr->get( 'consumerKey' ) ) );
+ $logEntry->setRelations( array(
+ 'OAuthConsumer' => array( $cmr->get(
'consumerKey' ) )
+ ) );
$logid = $logEntry->insert( $dbw );
- // @TODO: Core wrapper
- $dbw->insert( 'log_search',
- array(
- 'ls_field' => 'OAuthConsumer',
- 'ls_value' => $cmr->get( 'consumerKey'
),
- 'ls_log_id' => $logid ),
- __METHOD__,
- 'IGNORE'
- );
// @TODO: email/notifications?
@@ -301,16 +275,10 @@
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['reason'] );
$logEntry->setParameters( array( '4:consumer' =>
$cmr->get( 'consumerKey' ) ) );
+ $logEntry->setRelations( array(
+ 'OAuthConsumer' => array( $cmr->get(
'consumerKey' ) )
+ ) );
$logid = $logEntry->insert( $dbw );
- // @TODO: Core wrapper
- $dbw->insert( 'log_search',
- array(
- 'ls_field' => 'OAuthConsumer',
- 'ls_value' => $cmr->get( 'consumerKey'
),
- 'ls_log_id' => $logid ),
- __METHOD__,
- 'IGNORE'
- );
// @TODO: email/notifications?
@@ -340,16 +308,10 @@
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['reason'] );
$logEntry->setParameters( array( '4:consumer' =>
$cmr->get( 'consumerKey' ) ) );
+ $logEntry->setRelations( array(
+ 'OAuthConsumer' => array( $cmr->get(
'consumerKey' ) )
+ ) );
$logid = $logEntry->insert( $dbw );
- // @TODO: Core wrapper
- $dbw->insert( 'log_search',
- array(
- 'ls_field' => 'OAuthConsumer',
- 'ls_value' => $cmr->get( 'consumerKey'
),
- 'ls_log_id' => $logid ),
- __METHOD__,
- 'IGNORE'
- );
// @TODO: email/notifications?
diff --git a/control/MWOAuthDAOAccessControl.php
b/control/MWOAuthDAOAccessControl.php
index bb6054a..d303534 100644
--- a/control/MWOAuthDAOAccessControl.php
+++ b/control/MWOAuthDAOAccessControl.php
@@ -69,8 +69,8 @@
*/
final public function get( $name, $sCallback = null ) {
$msg = $this->dao->userCanAccess( $name, $this->context );
- if ( $msg instanceof Message ) {
- return $msg;
+ if ( $msg !== true ) {
+ return $msg; // should be a Message object
} else {
$value = $this->dao->get( $name );
return $sCallback ? call_user_func( $sCallback, $value
) : $value;
diff --git a/control/MWOAuthSubmitControl.php b/control/MWOAuthSubmitControl.php
index c8fa742..9829898 100644
--- a/control/MWOAuthSubmitControl.php
+++ b/control/MWOAuthSubmitControl.php
@@ -94,12 +94,18 @@
*/
protected function validateFields( array $required ) {
foreach ( $required as $field => $validator ) {
- if ( is_null( $this->vals[$field] ) ) {
+ if ( !isset( $this->vals[$field] ) ) {
// @TODO: check for field-specific message first
return $this->failure( "missing_field_$field",
'mwoauth-missing-field', $field );
+ } elseif ( !is_scalar( $this->vals[$field] ) ) {
+ // @TODO: check for field-specific message first
+ return $this->failure( "invalid_field_$field",
'mwoauth-invalid-field', $field );
+ }
+ if ( is_string( $this->vals[$field] ) ) {
+ $this->vals[$field] = trim( $this->vals[$field]
); // trim all input
}
$valid = is_string( $validator ) // regex
- ? is_scalar( $this->vals[$field] ) &&
preg_match( $validator, $this->vals[$field] )
+ ? preg_match( $validator, $this->vals[$field] )
: $validator( $this->vals[$field] );
if ( !$valid ) {
// @TODO: check for field-specific message first
diff --git a/frontend/MWOAuthUI.setup.php b/frontend/MWOAuthUI.setup.php
index 1f83b48..f2343f7 100644
--- a/frontend/MWOAuthUI.setup.php
+++ b/frontend/MWOAuthUI.setup.php
@@ -15,6 +15,7 @@
$groups['MWOAuthConsumerRegistration'] = 'users';
$pages['MWOAuthManageConsumers'] =
'MWOAuthManageConsumers';
$groups['MWOAuthManageConsumers'] = 'users';
+ $pages['MWOAuthManageMyGrants'] =
'MWOAuthManageMyGrants';
}
}
diff --git a/frontend/language/MWOAuth.i18n.php
b/frontend/language/MWOAuth.i18n.php
index f2baee1..97b70eb 100644
--- a/frontend/language/MWOAuth.i18n.php
+++ b/frontend/language/MWOAuth.i18n.php
@@ -20,15 +20,17 @@
'mwoauth-consumer-key' => 'Consumer key:',
'mwoauth-consumer-name' => 'Application name:',
'mwoauth-consumer-version' => 'Major version:',
+ 'mwoauth-consumer-user' => 'Publisher:',
'mwoauth-consumer-stage' => 'Current status:',
'mwoauth-consumer-email' => 'Contact E-mail address:',
'mwoauth-consumer-description' => 'Application description:',
'mwoauth-consumer-callbackurl' => 'OAuth "callback" URL:',
- 'mwoauth-consumer-grantsneeded' => 'Grants used (JSON):',
- 'mwoauth-consumer-wiki' => 'Single-wiki usage:',
+ 'mwoauth-consumer-grantsneeded' => 'Applicable grants (JSON):',
+ 'mwoauth-consumer-wiki' => 'Applicable wiki:',
'mwoauth-consumer-restrictions' => 'Usage restictions (JSON):',
'mwoauth-consumer-rsakey' => 'Consumer RSA key:',
'mwoauth-consumer-secretkey' => 'Consumer secret token:',
+ 'mwoauth-consumer-accesstoken' => 'Access token:',
'mwoauth-consumer-reason' => 'Reason:',
'mwoauth-consumer-alreadyexists' => 'A consumer with this
name/version/author combination already exists',
'mwoauth-consumer-not-accepted' => 'Cannot update information for a
pending consumer request',
@@ -37,6 +39,7 @@
'mwoauth-consumer-not-disabled' => 'The consumer is not currently
disabled',
'mwoauth-consumer-not-approved' => 'The consumer is not approved (it
may have been disabled)',
'mwoauth-invalid-consumer-key' => 'No consumer exists with the given
key.',
+ 'mwoauth-invalid-access-token' => 'No access token exists with the
given key.',
'mwoauth-consumer-stage-proposed' => 'proposed',
'mwoauth-consumer-stage-rejected' => 'rejected',
@@ -112,6 +115,32 @@
'mwoauthmanageconsumers-success-disabled' => 'Consumer successfuly
disabled.',
'mwoauthmanageconsumers-success-reanable' => 'Consumer successfuly
re-enabled.',
+ 'mwoauthmanagemygrants' => 'Manage account OAuth grants',
+ 'mwoauthmanagemygrants-navigation' => 'Navigation:',
+ 'mwoauthmanagemygrants-showlist' => 'Consumer list',
+ 'mwoauthmanagemygrants-none' => 'No consumers have access on behalf of
your account.',
+ 'mwoauthmanagemygrants-name' => 'Consumer name',
+ 'mwoauthmanagemygrants-user' => 'Publisher',
+ 'mwoauthmanagemygrants-description' => 'Description',
+ 'mwoauthmanagemygrants-wiki' => 'Applicable wiki',
+ 'mwoauthmanagemygrants-wikiallowed' => 'Allowed on wiki',
+ 'mwoauthmanagemygrants-grants' => 'Applicable grants',
+ 'mwoauthmanagemygrants-grantsallowed' => 'Grants allowed:',
+ 'mwoauthmanagemygrants-applicablegrantsallowed' => 'Applicable grants
allowed:',
+ 'mwoauthmanagemygrants-consumerkey' => 'Consumer key',
+ 'mwoauthmanagemygrants-review' => 'Review/manage access',
+ 'mwoauthmanagemygrants-grantaccept' => 'Granted to consumer',
+ 'mwoauthmanagemygrants-confirm-text' => 'Use the form below to revoke
access or grants for an OAuth consumer to act on your behalf.
+
+Note that if you authorized a consumer to only have access to a subset of
wikis (site projects), then there will be multiple access tokens for that
consumer.',
+ 'mwoauthmanagemygrants-confirm-legend' => 'Manage consumer access
token',
+ 'mwoauthmanagemygrants-update' => 'Update access token grants',
+ 'mwoauthmanagemygrants-renounce' => 'De-authorize and delete access
token',
+ 'mwoauthmanagemygrants-action' => 'Change status:',
+ 'mwoauthmanagemygrants-confirm-submit' => 'Update access token status',
+ 'mwoauthmanagemygrants-success-update' => 'The access token for this
consumer was successfully updated.',
+ 'mwoauthmanagemygrants-success-renounce' => 'The access token for this
consumer was successfully deleted.',
+
'mwoauth-logentry-consumer-propose' => 'proposed an OAuth consumer
(consumer key $2)',
'mwoauth-logentry-consumer-update' => 'updated an OAuth consumer
(consumer key $2)',
'mwoauth-logentry-consumer-approve' => 'approved an OAuth consumer by
$1 (consumer key $2)',
diff --git a/frontend/specialpages/actions/MWOAuthManageConsumers.php
b/frontend/specialpages/actions/MWOAuthManageConsumers.php
index d524b0c..267c214 100644
--- a/frontend/specialpages/actions/MWOAuthManageConsumers.php
+++ b/frontend/specialpages/actions/MWOAuthManageConsumers.php
@@ -76,8 +76,6 @@
break;
}
- $this->addQueueSubtitleLinks( $consumerKey );
-
if ( $this->stage !== null ) {
$this->stageKey = $stageKey;
if ( $consumerKey ) {
@@ -88,6 +86,8 @@
} else {
$this->showMainHub();
}
+
+ $this->addQueueSubtitleLinks( $consumerKey );
$this->getOutput()->addModules( 'ext.MWOAuth' ); // CSS
}
@@ -103,21 +103,21 @@
$listLinks = array();
if ( $consumerKey || $this->stage !==
MWOAuthConsumer::STAGE_PROPOSED ) {
$listLinks[] = Linker::linkKnown(
- SpecialPage::getSafeTitleFor(
'MWOAuthManageConsumers', 'proposed' ),
+ $this->getTitle( 'proposed' ),
$this->msg(
'mwoauthmanageconsumers-showproposed' )->escaped() );
} else {
$listLinks[] = $this->msg(
'mwoauthmanageconsumers-showproposed' )->escaped();
}
if ( $consumerKey || $this->stage !==
MWOAuthConsumer::STAGE_REJECTED ) {
$listLinks[] = Linker::linkKnown(
- SpecialPage::getSafeTitleFor(
'MWOAuthManageConsumers', 'rejected' ),
+ $this->getTitle( 'rejected' ),
$this->msg(
'mwoauthmanageconsumers-showrejected' )->escaped() );
} else {
$listLinks[] = $this->msg(
'mwoauthmanageconsumers-showrejected' )->escaped();
}
if ( $consumerKey || $this->stage !==
MWOAuthConsumer::STAGE_EXPIRED ) {
$listLinks[] = Linker::linkKnown(
- SpecialPage::getSafeTitleFor(
'MWOAuthManageConsumers', 'expired' ),
+ $this->getTitle( 'expired' ),
$this->msg(
'mwoauthmanageconsumers-showexpired' )->escaped() );
} else {
$listLinks[] = $this->msg(
'mwoauthmanageconsumers-showexpired' )->escaped();
@@ -128,15 +128,8 @@
$viewall = $this->msg( 'parentheses' )->rawParams(
Linker::linkKnown(
$this->getTitle(), $this->msg(
'mwoauthmanageconsumers-main' )->escaped() ) );
- // Give grep a chance to find the usages:
- // mwoauthmanageconsumers-type-proposed,
mwoauthmanageconsumers-type-reject,
- // mwoauthmanageconsumers-type-expired
$this->getOutput()->setSubtitle(
"<strong>" . $this->msg( 'mwoauthmanageconsumers-type'
)->escaped() . " <i>" .
- ( $this->stageKey !== null
- ? $this->msg(
"mwoauthmanageconsumers-type-{$this->stageKey}" )->escaped()
- : ''
- ) .
"</i></strong> [{$linkHtml}]
<strong>{$viewall}</strong>" );
}
@@ -171,7 +164,7 @@
'<li>' .
"<$tag>" .
Linker::makeKnownLinkObj(
- SpecialPage::getSafeTitleFor(
'MWOAuthManageConsumers', $stageKey ),
+ $this->getTitle( $stageKey ),
// Give grep a chance to find the
usages:
// mwoauthmanageconsumers-q-proposed,
mwoauthmanageconsumers-q-reject,
// mwoauthmanageconsumers-q-expired
@@ -189,7 +182,7 @@
$out->addHTML(
'<li>' .
Linker::makeKnownLinkObj(
- SpecialPage::getSafeTitleFor(
'MWOAuthManageConsumers', $stageKey ),
+ $this->getTitle( $stageKey ),
// Give grep a chance to find the
usages:
// mwoauthmanageconsumers-l-proposed,
mwoauthmanageconsumers-l-reject,
// mwoauthmanageconsumers-l-expired
@@ -243,6 +236,11 @@
'label-message' =>
'mwoauth-consumer-version',
'default' => $cmr->get( 'version' )
),
+ 'user' => array(
+ 'type' => 'info',
+ 'label-message' =>
'mwoauth-consumer-user',
+ 'default' => $cmr->get( 'userId',
array( 'User', 'whoIs' ) )
+ ),
'stage' => array(
'type' => 'info',
'label-message' =>
'mwoauth-consumer-stage',
@@ -286,6 +284,11 @@
'default' => $cmr->get( 'restrictions',
array( 'FormatJSON', 'encode' ) ),
'readonly' => true,
'rows' => 5
+ ),
+ 'secretKey' => array(
+ 'type' => 'info',
+ 'label-message' =>
'mwoauth-consumer-secretkey',
+ 'default' => $cmr->get( 'secretKey' )
),
'rsaKey' => array(
'type' => 'textarea',
@@ -335,6 +338,9 @@
$status = $form->show();
if ( $status instanceof Status && $status->isOk() ) {
$type =
self::$stageKeyMap[$status->value['result']->get( 'stage' )];
+ // Uses messages
mwoauthmanageconsumers-success-proposed,
+ // mwoauthmanageconsumers-success-rejected,
mwoauthmanageconsumers-success-approved,
+ // mwoauthmanageconsumers-success-disabled,
mwoauthmanageconsumers-success-reenabled
$this->getOutput()->addWikiMsg(
"mwoauthmanageconsumers-success-$type" );
$this->getOutput()->returnToMain();
} else {
@@ -392,7 +398,7 @@
$stageKey = self::$stageKeyMap[$cmr->get( 'stage' )];
$link = Linker::linkKnown(
- SpecialPage::getSafeTitleFor( 'MWOAuthManageConsumers',
"{$stageKey}/{$cmrKey}" ),
+ $this->getTitle( "{$stageKey}/{$cmrKey}" ),
$this->msg( 'mwoauthmanageconsumers-review' )->escaped()
);
--
To view, visit https://gerrit.wikimedia.org/r/72990
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I669bd4b750cdfafd18dad60d8cdabdc1675113f4
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/OAuth
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits