jenkins-bot has submitted this change and it was merged.
Change subject: Add owner-only consumers
......................................................................
Add owner-only consumers
An owner-only consumer is automatically approved, automatically
accepted by the owner, cannot be used by anyone other than the owner,
cannot use the usual authorization flow, and does not tag changes.
Bug: T87395
Bug: T121113
Change-Id: I3c791b949e19eb476968e5f9dd1511d485e52810
---
M api/MWOAuthAPI.setup.php
M backend/MWOAuthConsumer.php
M backend/MWOAuthServer.php
M backend/schema/MWOAuthUpdater.hooks.php
M backend/schema/mysql/OAuth.sql
A backend/schema/mysql/owner_only.sql
M backend/schema/sqlite/OAuth.sql
A backend/schema/sqlite/owner_only.sql
M control/MWOAuthConsumerAcceptanceSubmitControl.php
M control/MWOAuthConsumerSubmitControl.php
M frontend/specialpages/SpecialMWOAuth.php
M frontend/specialpages/SpecialMWOAuthConsumerRegistration.php
M frontend/specialpages/SpecialMWOAuthManageConsumers.php
M i18n/en.json
M i18n/qqq.json
15 files changed, 205 insertions(+), 50 deletions(-)
Approvals:
CSteipp: Looks good to me, but someone else must approve
Gergő Tisza: Looks good to me, approved
jenkins-bot: Verified
diff --git a/api/MWOAuthAPI.setup.php b/api/MWOAuthAPI.setup.php
index b2d80e8..02c2b72 100755
--- a/api/MWOAuthAPI.setup.php
+++ b/api/MWOAuthAPI.setup.php
@@ -115,9 +115,7 @@
// The consumer is approved or owned by
$localUser, and is for this wiki.
$consumer = MWOAuthConsumer::newFromId( $dbr,
$access->get( 'consumerId' ) );
- if ( $consumer->get( 'stage' ) !==
MWOAuthConsumer::STAGE_APPROVED
- && !$consumer->isPendingAndOwnedBy(
$localUser ) // let publisher test this
- ) {
+ if ( !$consumer->isUsableBy( $localUser ) ) {
throw self::makeException(
'mwoauth-invalid-authorization-not-approved' );
} elseif ( $consumer->get( 'wiki' ) !== '*'
&& $consumer->get( 'wiki' ) !== $wiki
@@ -301,12 +299,15 @@
$dbr = MWOAuthUtils::getCentralDB( DB_SLAVE );
$access = MWOAuthConsumerAcceptance::newFromToken(
$dbr, $accesstoken->key );
$consumerId = $access->get( 'consumerId' );
- \ChangeTags::addTags(
- "OAuth CID: $consumerId",
- $rc->mAttribs['rc_id'],
- $rc->mAttribs['rc_this_oldid'],
- $rc->mAttribs['rc_logid']
- );
+ $consumer = MWOAuthConsumer::newFromId( $dbr,
$consumerId );
+ if ( !$consumer->get( 'ownerOnly' ) ) {
+ \ChangeTags::addTags(
+ "OAuth CID: $consumerId",
+ $rc->mAttribs['rc_id'],
+ $rc->mAttribs['rc_this_oldid'],
+ $rc->mAttribs['rc_logid']
+ );
+ }
}
return true;
}
diff --git a/backend/MWOAuthConsumer.php b/backend/MWOAuthConsumer.php
index 76631fb..3d14873 100644
--- a/backend/MWOAuthConsumer.php
+++ b/backend/MWOAuthConsumer.php
@@ -47,6 +47,8 @@
protected $emailAuthenticated;
/** @var int User accepted the developer agreement */
protected $developerAgreement;
+ /** @var int Consumer is for use by the owner only */
+ protected $ownerOnly;
/** @var string Wiki ID the application can be used on (or "*" for all)
*/
protected $wiki;
/** @var string TS_MW timestamp of proposal */
@@ -88,6 +90,7 @@
'email' => 'oarc_email',
'emailAuthenticated' =>
'oarc_email_authenticated',
'developerAgreement' =>
'oarc_developer_agreement',
+ 'ownerOnly' => 'oarc_owner_only',
'wiki' => 'oarc_wiki',
'grants' => 'oarc_grants',
'registration' => 'oarc_registration',
@@ -215,13 +218,20 @@
}
/**
- * Check if the consumer is still pending approval and is owned by $user
+ * Check if the consumer is usable by $user
+ *
+ * "Usable by $user" includes:
+ * - Approved for multi-user use
+ * - Approved for owner-only use and is owned by $user
+ * - Still pending approval and is owned by $user
*
* @param \User $user
* @return boolean
*/
- public function isPendingAndOwnedBy( \User $user ) {
- if ( $this->stage === self::STAGE_PROPOSED ) {
+ public function isUsableBy( \User $user ) {
+ if ( $this->stage === self::STAGE_APPROVED && !$this->get(
'ownerOnly' ) ) {
+ return true;
+ } elseif ( $this->stage === self::STAGE_PROPOSED ||
$this->stage === self::STAGE_APPROVED ) {
$centralId = MWOAuthUtils::getCentralIdFromLocalUser(
$user );
return ( $centralId && $this->userId === $centralId );
}
diff --git a/backend/MWOAuthServer.php b/backend/MWOAuthServer.php
index c0ba27a..0300cc0 100644
--- a/backend/MWOAuthServer.php
+++ b/backend/MWOAuthServer.php
@@ -26,6 +26,16 @@
$consumer = $this->get_consumer( $request );
+ // Consumer must not be owner-only
+ if ( $consumer->get( 'ownerOnly' ) ) {
+ throw new MWOAuthException(
'mwoauthserver-consumer-owner-only', array(
+ $consumer->get( 'name' ),
+ \SpecialPage::getTitleFor(
+ 'OAuthConsumerRegistration', 'update/'
. $consumer->get( 'consumerKey' )
+ )
+ ) );
+ }
+
// Consumer must have a key for us to verify
if ( !$consumer->get( 'secretKey' ) && !$consumer->get(
'rsaKey' ) ) {
throw new MWOAuthException(
'mwoauthserver-consumer-no-secret' );
@@ -105,6 +115,16 @@
$this->get_version( $request );
$consumer = $this->get_consumer( $request );
+
+ // Consumer must not be owner-only
+ if ( $consumer->get( 'ownerOnly' ) ) {
+ throw new MWOAuthException(
'mwoauthserver-consumer-owner-only', array(
+ $consumer->get( 'name' ),
+ \SpecialPage::getTitleFor(
+ 'OAuthConsumerRegistration', 'update/'
. $consumer->get( 'consumerKey' )
+ )
+ ) );
+ }
// Consumer must have a key for us to verify
if ( !$consumer->get( 'secretKey' ) && !$consumer->get(
'rsaKey' ) ) {
@@ -186,9 +206,7 @@
$consumer = $this->data_store->lookup_consumer( $consumerKey );
if ( !$consumer || $consumer->get( 'deleted' ) ) {
throw new MWOAuthException(
'mwoauthserver-bad-consumer-key' );
- } elseif ( $consumer->get( 'stage' ) !==
MWOAuthConsumer::STAGE_APPROVED
- && !$consumer->isPendingAndOwnedBy( $mwUser ) // let
publisher test this
- ) {
+ } elseif ( !$consumer->isUsableBy( $mwUser ) ) {
$owner = MWOAuthUtils::getCentralUserNameFromId(
$consumer->get( 'userId' ),
$mwUser
@@ -197,6 +215,13 @@
'mwoauthserver-bad-consumer',
array( $consumer->get( 'name' ),
MWOAuthUtils::getCentralUserTalk( $owner ) )
);
+ } elseif ( $consumer->get( 'ownerOnly' ) ) {
+ throw new MWOAuthException(
'mwoauthserver-consumer-owner-only', array(
+ $consumer->get( 'name' ),
+ \SpecialPage::getTitleFor(
+ 'OAuthConsumerRegistration', 'update/'
. $consumer->get( 'consumerKey' )
+ )
+ ) );
}
// Generate and Update the tokens:
diff --git a/backend/schema/MWOAuthUpdater.hooks.php
b/backend/schema/MWOAuthUpdater.hooks.php
index 611b508..90bf2ae 100644
--- a/backend/schema/MWOAuthUpdater.hooks.php
+++ b/backend/schema/MWOAuthUpdater.hooks.php
@@ -39,6 +39,14 @@
true
) );
+ $updater->addExtensionUpdate( array(
+ 'addField',
+ 'oauth_registered_consumer',
+ 'oarc_owner_only',
+ "$base/owner_only.sql",
+ true
+ ) );
+
} elseif ( $dbType == 'postgres' ) {
//$base = "$base/postgres";
diff --git a/backend/schema/mysql/OAuth.sql b/backend/schema/mysql/OAuth.sql
index 6b96d3b..4edb72b 100644
--- a/backend/schema/mysql/OAuth.sql
+++ b/backend/schema/mysql/OAuth.sql
@@ -29,6 +29,8 @@
oarc_email_authenticated varbinary(14) NULL,
-- Did the owner accept the developer agreement?
oarc_developer_agreement tinyint NOT NULL DEFAULT 0,
+ -- Is this consumer owner-only
+ oarc_owner_only tinyint NOT NULL DEFAULT 0,
-- What wiki this is allowed on (a single wiki or '*' for all)
oarc_wiki varbinary(32) NOT NULL,
-- Grants needed for client consumers
diff --git a/backend/schema/mysql/owner_only.sql
b/backend/schema/mysql/owner_only.sql
new file mode 100644
index 0000000..f231f41
--- /dev/null
+++ b/backend/schema/mysql/owner_only.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/oauth_registered_consumer ADD COLUMN `oarc_owner_only`
tinyint NOT NULL DEFAULT 0 AFTER `oarc_developer_agreement`;
diff --git a/backend/schema/sqlite/OAuth.sql b/backend/schema/sqlite/OAuth.sql
index 6b96d3b..4edb72b 100644
--- a/backend/schema/sqlite/OAuth.sql
+++ b/backend/schema/sqlite/OAuth.sql
@@ -29,6 +29,8 @@
oarc_email_authenticated varbinary(14) NULL,
-- Did the owner accept the developer agreement?
oarc_developer_agreement tinyint NOT NULL DEFAULT 0,
+ -- Is this consumer owner-only
+ oarc_owner_only tinyint NOT NULL DEFAULT 0,
-- What wiki this is allowed on (a single wiki or '*' for all)
oarc_wiki varbinary(32) NOT NULL,
-- Grants needed for client consumers
diff --git a/backend/schema/sqlite/owner_only.sql
b/backend/schema/sqlite/owner_only.sql
new file mode 100644
index 0000000..c0ddbfa
--- /dev/null
+++ b/backend/schema/sqlite/owner_only.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/oauth_registered_consumer ADD COLUMN `oarc_owner_only`
tinyint NOT NULL DEFAULT 0;
diff --git a/control/MWOAuthConsumerAcceptanceSubmitControl.php
b/control/MWOAuthConsumerAcceptanceSubmitControl.php
index 90913df..38f9fb4 100644
--- a/control/MWOAuthConsumerAcceptanceSubmitControl.php
+++ b/control/MWOAuthConsumerAcceptanceSubmitControl.php
@@ -89,9 +89,7 @@
$cmr = MWOAuthConsumer::newFromKey( $dbw,
$this->vals['consumerKey'] );
if ( !$cmr ) {
return $this->failure( 'invalid_consumer_key',
'mwoauth-invalid-consumer-key' );
- } elseif ( $cmr->get( 'stage' ) !==
MWOAuthConsumer::STAGE_APPROVED
- && !$cmr->isPendingAndOwnedBy( $user ) // let
publisher test this
- ) {
+ } elseif ( !$cmr->isUsableBy( $user ) ) {
return $this->failure( 'permission_denied',
'badaccess-group0' );
}
diff --git a/control/MWOAuthConsumerSubmitControl.php
b/control/MWOAuthConsumerSubmitControl.php
index 4bb2c5a..dc287b8 100644
--- a/control/MWOAuthConsumerSubmitControl.php
+++ b/control/MWOAuthConsumerSubmitControl.php
@@ -64,8 +64,9 @@
'propose' => array(
'name' => '/^.{1,128}$/',
'version' =>
'/^\d{1,3}(\.\d{1,2}){0,2}(-(dev|alpha|beta))?$/',
- 'callbackUrl' => function( $s ) {
- return wfParseUrl( $s ) !== null; },
+ 'callbackUrl' => function( $s, $vals ) {
+ return $vals['ownerOnly'] ||
wfParseUrl( $s ) !== null;
+ },
'description' => '/^.*$/s',
'email' => function( $s ) {
return \Sanitizer::validateEmail( $s );
},
@@ -185,6 +186,16 @@
'mwoauth-consumer-alreadyexistsversion', $curVer );
}
+ // Handle owner-only mode
+ if ( $this->vals['ownerOnly'] ) {
+ $this->vals['callbackUrl'] =
\SpecialPage::getTitleFor( 'OAuth', 'verified' )
+ ->getLocalUrl();
+ $this->vals['callbackIsPrefix'] = '';
+ $stage = MWOAuthConsumer::STAGE_APPROVED;
+ } else {
+ $stage = MWOAuthConsumer::STAGE_PROPOSED;
+ }
+
// Handle grant types
$grants = array();
switch( $this->vals['granttype'] ) {
@@ -213,7 +224,7 @@
'developerAgreement' => 1,
'secretKey' =>
\MWCryptRand::generateHex( 32 ),
'registration' => $now,
- 'stage' =>
MWOAuthConsumer::STAGE_PROPOSED,
+ 'stage' => $stage,
'stageTimestamp' => $now,
'grants' => $grants,
'restrictions' =>
\FormatJSON::decode( $this->vals['restrictions'], true ),
@@ -222,7 +233,10 @@
);
$cmr->save( $dbw );
- $logEntry = new \ManualLogEntry( 'mwoauthconsumer',
'propose' );
+ $logEntry = new \ManualLogEntry(
+ 'mwoauthconsumer',
+ $cmr->get( 'ownerOnly' ) ? 'create-owner-only'
: 'propose'
+ );
$logEntry->setPerformer( $user );
$logEntry->setTarget( $this->getLogTitle( $dbw,
$cmr->get( 'userId' ) ) );
$logEntry->setComment( $this->vals['description'] );
@@ -232,7 +246,24 @@
) );
$logEntry->insert( $dbw );
- return $this->success( $cmr );
+ // If it's owner-only, automatically accept it for the
user too.
+ $cmra = null;
+ if ( $cmr->get( 'ownerOnly' ) ) {
+ $accessToken = MWOAuthDataStore::newToken();
+ $cmra =
MWOAuthConsumerAcceptance::newFromArray( array(
+ 'id' => null,
+ 'wiki' => $cmr->get( 'wiki' ),
+ 'userId' => $centralUserId,
+ 'consumerId' => $cmr->get( 'id' ),
+ 'accessToken' => $accessToken->key,
+ 'accessSecret' => $accessToken->secret,
+ 'grants' => $cmr->get( 'grants' ),
+ 'accepted' => $now,
+ ) );
+ $cmra->save( $dbw );
+ }
+
+ return $this->success( array( 'consumer' => $cmr,
'acceptance' => $cmra ) );
case 'update':
if ( !$user->isAllowed( 'mwoauthupdateownconsumer' ) ) {
return $this->failure( 'permission_denied',
'badaccess-group0' );
@@ -274,7 +305,32 @@
$logEntry->insert( $dbw );
}
- return $this->success( $cmr );
+ $cmra = null;
+ if ( $cmr->get( 'ownerOnly' ) &&
$this->vals['resetSecret'] ) {
+ $accessToken = MWOAuthDataStore::newToken();
+ $fields = array(
+ 'wiki' => $cmr->get( 'wiki' ),
+ 'userId' => $centralUserId,
+ 'consumerId' => $cmr->get( 'id' ),
+ 'accessSecret' => $accessToken->secret,
+ 'grants' => $cmr->get( 'grants' ),
+ );
+
+ $oauthServer = MWOAuthUtils::newMWOAuthServer();
+ $cmra = $oauthServer->getCurrentAuthorization(
$user, $cmr, wfWikiId() );
+ if ( $cmra ) {
+ $cmra->setFields( $fields );
+ } else {
+ $cmra =
MWOAuthConsumerAcceptance::newFromArray( $fields + array(
+ 'id' => null,
+ 'accessToken' =>
$accessToken->key,
+ 'accepted' =>
wfTimestampNow(),
+ ) );
+ }
+ $cmra->save( $dbw );
+ }
+
+ return $this->success( array( 'consumer' => $cmr,
'acceptance' => $cmra ) );
case 'approve':
if ( !$user->isAllowed( 'mwoauthmanageconsumer' ) ) {
return $this->failure( 'permission_denied',
'badaccess-group0' );
diff --git a/frontend/specialpages/SpecialMWOAuth.php
b/frontend/specialpages/SpecialMWOAuth.php
index c26d9cb..31e07b6 100644
--- a/frontend/specialpages/SpecialMWOAuth.php
+++ b/frontend/specialpages/SpecialMWOAuth.php
@@ -291,9 +291,7 @@
);
if ( !$cmr ) {
throw new MWOAuthException(
'mwoauthserver-bad-consumer-key' );
- } elseif ( $cmr->get( 'stage' ) !==
MWOAuthConsumer::STAGE_APPROVED
- && !$cmr->getDAO()->isPendingAndOwnedBy( $user )
- ) {
+ } elseif ( !$cmr->getDAO()->isUsableBy( $user ) ) {
throw new MWOAuthException(
'mwoauthserver-bad-consumer',
array(
diff --git a/frontend/specialpages/SpecialMWOAuthConsumerRegistration.php
b/frontend/specialpages/SpecialMWOAuthConsumerRegistration.php
index 1df807a..82abb33 100644
--- a/frontend/specialpages/SpecialMWOAuthConsumerRegistration.php
+++ b/frontend/specialpages/SpecialMWOAuthConsumerRegistration.php
@@ -116,15 +116,22 @@
'required' => true,
'rows' => 5
),
+ 'ownerOnly' => array(
+ 'type' => 'check',
+ 'label-message' => array(
'mwoauth-consumer-owner-only', $user->getName() ),
+ 'help-message' => array(
'mwoauth-consumer-owner-only-help', $user->getName() ),
+ ),
'callbackUrl' => array(
'type' => 'text',
'label-message' =>
'mwoauth-consumer-callbackurl',
- 'required' => true
+ 'required' => true,
+ 'hide-if' => array( '!==',
'ownerOnly', '' ),
),
'callbackIsPrefix' => array(
'type' => 'check',
'label-message' =>
'mwoauth-consumer-callbackisprefix',
- 'required' => true
+ 'required' => true,
+ 'hide-if' => array( '!==',
'ownerOnly', '' ),
),
'email' => array(
'type' => 'text',
@@ -157,7 +164,7 @@
'type' => 'checkmatrix',
'label-message' =>
'mwoauth-consumer-grantsneeded',
'help-message' =>
'mwoauth-consumer-grantshelp',
- 'hide-if' => array( '!==',
'wpgranttype', 'normal' ),
+ 'hide-if' => array( '!==',
'granttype', 'normal' ),
'columns' => array(
$this->msg(
'mwoauth-consumer-required-grant' )->escaped() => 'grant'
),
@@ -223,9 +230,20 @@
$status = $form->show();
if ( $status instanceof \Status && $status->isOk() ) {
- $this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-proposed',
- $status->value['result']->get(
'consumerKey' ),
- MWOAuthUtils::hmacDBSecret(
$status->value['result']->get( 'secretKey' ) ) );
+ $cmr = $status->value['result']['consumer'];
+ if ( $cmr->get( 'ownerOnly' ) ) {
+ $cmra =
$status->value['result']['acceptance'];
+ $this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-created-owner-only',
+ $cmr->get( 'consumerKey' ),
+ MWOAuthUtils::hmacDBSecret(
$cmr->get( 'secretKey' ) ),
+ $cmra->get( 'accessToken' ),
+ MWOAuthUtils::hmacDBSecret(
$cmra->get( 'accessSecret' ) )
+ );
+ } else {
+ $this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-proposed',
+ $cmr->get( 'consumerKey' ),
+ MWOAuthUtils::hmacDBSecret(
$cmr->get( 'secretKey' ) ) );
+ }
$this->getOutput()->returnToMain();
}
break;
@@ -322,11 +340,22 @@
$status = $form->show();
if ( $status instanceof \Status && $status->isOk() ) {
+ $cmr = $status->value['result']['consumer'];
$this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-updated' );
- $curSecretKey = $status->value['result']->get(
'secretKey' );
+ $curSecretKey = $cmr->get( 'secretKey' );
if ( $oldSecretKey !== $curSecretKey ) { //
token reset?
- $this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-secretreset',
- MWOAuthUtils::hmacDBSecret(
$curSecretKey ) );
+ if ( $cmr->get( 'ownerOnly' ) ) {
+ $cmra =
$status->value['result']['acceptance'];
+ $this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-secretreset-owner-only',
+ $cmr->get(
'consumerKey' ),
+
MWOAuthUtils::hmacDBSecret( $curSecretKey ),
+ $cmra->get(
'accessToken' ),
+
MWOAuthUtils::hmacDBSecret( $cmra->get( 'accessSecret' ) )
+ );
+ } else {
+ $this->getOutput()->addWikiMsg(
'mwoauthconsumerregistration-secretreset',
+
MWOAuthUtils::hmacDBSecret( $curSecretKey ) );
+ }
}
$this->getOutput()->returnToMain();
} else {
diff --git a/frontend/specialpages/SpecialMWOAuthManageConsumers.php
b/frontend/specialpages/SpecialMWOAuthManageConsumers.php
index 8959e61..81d6cae 100755
--- a/frontend/specialpages/SpecialMWOAuthManageConsumers.php
+++ b/frontend/specialpages/SpecialMWOAuthManageConsumers.php
@@ -242,6 +242,21 @@
}
}
+ $owner = $cmr->get( 'userId', function( $s ) {
+ $name = MWOAuthUtils::getCentralUserNameFromId( $s );
+ return $name;
+ } );
+
+ $link = \Linker::linkKnown(
+ $title = \SpecialPage::getTitleFor(
'OAuthListConsumers' ),
+ wfMessage( 'mwoauthmanageconsumers-search-publisher'
)->escaped(),
+ array(),
+ array( 'publisher' => $owner )
+ );
+ $ownerLink = htmlspecialchars( $owner ) . ' ' .
+ wfMessage( 'parentheses' )->rawParams( $link
)->escaped();
+ $ownerOnly = $cmr->get( 'ownerOnly' );
+
$dbw = MWOAuthUtils::getCentralDB( DB_MASTER ); // @TODO: lazy
handle
$control = new MWOAuthConsumerSubmitControl(
$this->getContext(), array(), $dbw );
$form = new \HTMLForm(
@@ -274,17 +289,7 @@
'user' => array(
'type' => 'info',
'label-message' =>
'mwoauth-consumer-user',
- 'default' => $cmr->get( 'userId',
function( $s ) {
- $name =
MWOAuthUtils::getCentralUserNameFromId( $s );
- $link = \Linker::linkKnown(
- $title =
\SpecialPage::getTitleFor( 'OAuthListConsumers' ),
- wfMessage(
'mwoauthmanageconsumers-search-publisher' )->escaped(),
- array(),
- array( 'publisher' =>
$name )
- );
- return htmlspecialchars( $name
) . ' ' .
- wfMessage(
'parentheses' )->rawParams( $link )->escaped();
- } ),
+ 'default' => $ownerLink,
'raw' => true
),
'description' => array(
@@ -293,13 +298,18 @@
'default' => $cmr->get( 'description' ),
'rows' => 5
),
+ 'ownerOnly' => array(
+ 'type' => $ownerOnly ? 'info' :
'hidden',
+ 'label-message' =>
'mwoauth-consumer-owner-only-label',
+ 'default' => wfMessage(
'mwoauth-consumer-owner-only', $owner )->escaped(),
+ ),
'callbackUrl' => array(
- 'type' => 'info',
+ 'type' => $ownerOnly ? 'hidden' :
'info',
'label-message' =>
'mwoauth-consumer-callbackurl',
- 'default' => $cmr->get( 'callbackUrl' )
+ 'default' => $cmr->get( 'callbackUrl' ),
),
'callbackIsPrefix' => array(
- 'type' => 'info',
+ 'type' => $ownerOnly ? 'hidden' :
'info',
'label-message' =>
'mwoauth-consumer-callbackisprefix',
'default' => $cmr->get(
'callbackIsPrefix' )
),
diff --git a/i18n/en.json b/i18n/en.json
index 8616f1d..1dcc801 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -21,6 +21,9 @@
"mwoauth-consumer-user": "Publisher:",
"mwoauth-consumer-stage": "Current status:",
"mwoauth-consumer-email": "Contact email address:",
+ "mwoauth-consumer-owner-only-label": "Owner-only:",
+ "mwoauth-consumer-owner-only": "This consumer is for use only by $1.",
+ "mwoauth-consumer-owner-only-help": "Selecting this option will cause
the consumer to be automatically approved and accepted for use by $1. It will
not be usable by any other user, and the usual authorization flow will not
function. Actions taken using this consumer will not be tagged.",
"mwoauth-consumer-description": "Application description:",
"mwoauth-consumer-callbackurl": "OAuth \"callback\" URL:",
"mwoauth-consumer-callbackisprefix": "Allow consumer to specify a
callback in requests and use \"callback\" URL above as a required prefix.",
@@ -81,8 +84,10 @@
"mwoauthconsumerregistration-manage": "manage",
"mwoauthconsumerregistration-resetsecretkey": "Reset the secret key to
a new value",
"mwoauthconsumerregistration-proposed": "Your OAuth consumer request
has been received.\n\nYou have been assigned a consumer token of '''$1''' and a
secret token of '''$2'''. ''Please record these for future reference.''",
+ "mwoauthconsumerregistration-created-owner-only": "Your OAuth consumer
has been created.\n\nYour tokens are:\n; Consumer token: $1\n; Consumer secret:
$2\n; Access token: $3\n; Access secret: $4\n<em>Please record these for future
reference.</em>",
"mwoauthconsumerregistration-updated": "Your OAuth consumer registry
was successfully updated.",
"mwoauthconsumerregistration-secretreset": "You have been assigned a
consumer secret token of '''$1'''. ''Please record this for future
reference.''",
+ "mwoauthconsumerregistration-secretreset-owner-only": "Your OAuth
consumer tokens have been reset. The new tokens are:\n; Consumer token: $1\n;
Consumer secret: $2\n; Access token: $3\n; Access secret: $4\n<em>Please record
these for future reference.</em>",
"oauthmanageconsumers": "Manage OAuth consumers",
"mwoauthmanageconsumers-notloggedin": "You have to be logged in to
access this page.",
"mwoauthmanageconsumers-type": "Queues:",
@@ -179,6 +184,7 @@
"logentry-mwoauthconsumer-reject": "$1 {{GENDER:$2|rejected}} an OAuth
consumer by $3 (consumer key $4)",
"logentry-mwoauthconsumer-disable": "$1 {{GENDER:$2|disabled}} an OAuth
consumer by $3 (consumer key $4)",
"logentry-mwoauthconsumer-reenable": "$1 {{GENDER:$2|re-enabled}} an
OAuth consumer by $3 (consumer key $4)",
+ "logentry-mwoauthconsumer-create-owner-only": "$1 {{GENDER:$2|created}}
an owner-only OAuth consumer (consumer key $4)",
"mwoauthconsumer-consumer-logpage": "OAuth consumer log",
"mwoauthconsumer-consumer-logpagetext": "Log of approvals, rejections,
and disabling of registered OAuth consumers.",
"mwoauth-bad-request-missing-params": "Sorry, something went wrong
configuring this connected application. <span
class=\"plainlinks\">[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:OAuth
Contact support]</span> to get help fixing it.\n\n<span class=\"plainlinks
mw-mwoautherror-details\">OAuth missing parameters,
[https://www.mediawiki.org/wiki/Help:OAuth/Errors#E001 E001]</span>",
@@ -199,6 +205,7 @@
"mwoauthserver-invalid-request-token": "Invalid token in your request.",
"mwoauthserver-invalid-user": "To use Connected Apps on this site, you
must have an account across all projects. When you have an account on all
projects, you can try to connect \"$1\" again.\n\n<span class=\"plainlinks
mw-mwoautherror-details\">Unified login needed,
[https://www.mediawiki.org/wiki/Help:OAuth/Errors#E008 E008]</span>",
"mwoauthserver-consumer-no-secret": "Sorry, something went wrong
connecting this application.\n\n<span class=\"plainlinks
mw-mwoautherror-details\">Consumer has no secret key,
[https://www.mediawiki.org/wiki/Help:OAuth/Errors#E009 E009]</span>",
+ "mwoauthserver-consumer-owner-only": "\"$1\" is an owner-only Connected
App. To fetch the access token, see [[$2]].\n\n<span class=\"plainlinks
mw-mwoautherror-details\">Consumer is owner-only,
[https://www.mediawiki.org/wiki/Help:OAuth/Errors#E010 E010]</span>",
"mwoauth-invalid-authorization-title": "OAuth authorization error",
"mwoauth-invalid-authorization": "The authorization headers in your
request are not valid: $1",
"mwoauth-invalid-authorization-wrong-wiki": "The authorization headers
in your request are not valid for $1",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 41da588..8eaa080 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -29,6 +29,9 @@
"mwoauth-consumer-user": "Used as label for the \"Central username\"
box.\n{{Identical|Publisher}}",
"mwoauth-consumer-stage": "Used as label for the \"Stage\"
value\n\nFollowed by any one of the following messages:\n*
{{msg-mw|Mwoauth-consumer-stage-proposed}}\n*
{{msg-mw|Mwoauth-consumer-stage-rejected}}\n*
{{msg-mw|Mwoauth-consumer-stage-expired}}\n*
{{msg-mw|Mwoauth-consumer-stage-approved}}\n*
{{msg-mw|Mwoauth-consumer-stage-disabled}}\n*
{{msg-mw|Mwoauth-consumer-stage-suppressed}}\n{{Identical|Current status}}",
"mwoauth-consumer-email": "Used as label for the \"Email address\"
input box.",
+ "mwoauth-consumer-owner-only-label": "Used as label for the \"Owner
only\" field.",
+ "mwoauth-consumer-owner-only": "Used as label for the \"Owner only\"
checkbox.",
+ "mwoauth-consumer-owner-only-help": "Used as help text for the \"Owner
only\" checkbox.",
"mwoauth-consumer-description": "Used as label for the \"description\"
textarea.\n{{Identical|Application description}}",
"mwoauth-consumer-callbackurl": "Used as label for the \"Callback URL\"
input box.\n\nSee [[w:Callback (computer programming)]].",
"mwoauth-consumer-callbackisprefix": "Used as a label for the check box
where user can decide if their consumer should use \"Callback URL\" as a string
prefix (checked), or if the consumer cannot customize the callback URL in its
requests as is required to specify \"oob\" (unchecked, default).",
@@ -89,8 +92,10 @@
"mwoauthconsumerregistration-manage": "Used as link
text.\n{{Identical|Manage}}",
"mwoauthconsumerregistration-resetsecretkey": "Used a label for a
checkbox",
"mwoauthconsumerregistration-proposed": "Used as success
message.\n\nParameters:\n* $1 - consumer key\n* $2 - secret key",
+ "mwoauthconsumerregistration-created-owner-only": "Used as success
message.\n\nParameters:\n* $1 - consumer key\n* $2 - consumer secret\n* $3 -
access key\n* $4 - access secret",
"mwoauthconsumerregistration-updated": "Shown as success message",
"mwoauthconsumerregistration-secretreset": "Shown on success message.
Parameters:\n* $1 - new secret token",
+ "mwoauthconsumerregistration-secretreset-owner-only": "Shown on success
message.\n\nParameters:\n* $1 - consumer key\n* $2 - consumer secret\n* $3 -
access key\n* $4 - access secret",
"oauthmanageconsumers":
"{{doc-special|MWOAuthManageConsumers}}\n{{Identical|Manage OAuth consumer}}",
"mwoauthmanageconsumers-notloggedin": "Used if the user is not logged
in.",
"mwoauthmanageconsumers-type": "Used as subtitle.\n\nFollowed by any
one (or zero) of the following messages:\n*
{{msg-mw|Mwoauthmanageconsumers-showproposed}}\n*
{{msg-mw|Mwoauthmanageconsumers-showrejected}}\n*
{{msg-mw|Mwoauthmanageconsumers-showexpired}}\n{{Identical|Queue}}",
@@ -187,6 +192,7 @@
"logentry-mwoauthconsumer-reject": "{{logentry}}\n* $4 - consumer key",
"logentry-mwoauthconsumer-disable": "{{logentry}}\n* $4 - consumer key",
"logentry-mwoauthconsumer-reenable": "{{logentry}}\n* $4 - consumer
key",
+ "logentry-mwoauthconsumer-create-owner-only": "{{logentry}}\n* $4 -
consumer key",
"mwoauthconsumer-consumer-logpage": "{{doc-logpage}}",
"mwoauthconsumer-consumer-logpagetext": "Description of the OAuth
consumer log.",
"mwoauth-bad-request-missing-params": "Error message when MediaWiki
makes an error during the authorization process, and fails to send all the
required url parameters",
@@ -207,6 +213,7 @@
"mwoauthserver-invalid-request-token": "Error message when an invalid
request token was submitted",
"mwoauthserver-invalid-user": "Error when the user attempts to use
OAuth, but they do not have a unified (SUL) account, which is
required.\n\nParameters:\n* $1 - application name",
"mwoauthserver-consumer-no-secret": "Error when a consumer with no
secret or RSA was submitted",
+ "mwoauthserver-consumer-owner-only": "Error when an owner-only consumer
attempted to use the authorization process",
"mwoauth-invalid-authorization-title": "Title of the error page when
the Authorization header is invalid",
"mwoauth-invalid-authorization": "Text of the error page when the
Authorization header is invalid. Parameters are:\n* $1 - Specific error message
from the OAuth layer, probably not localized",
"mwoauth-invalid-authorization-wrong-wiki": "Text of the error page
when the Authorization header is for the wrong wiki. Parameters are:\n* $1 -
wiki id",
--
To view, visit https://gerrit.wikimedia.org/r/255488
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I3c791b949e19eb476968e5f9dd1511d485e52810
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/OAuth
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: BryanDavis <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: Gergő Tisza <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: Springle <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits