Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CreateOAuthConsumer
0.00% covered (danger)
0.00%
0 / 71
0.00% covered (danger)
0.00%
0 / 2
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 1
90
1<?php
2/**
3 * Example:
4 *
5 * createOAuthConsumer.php
6 *   --callbackIsPrefix
7 *   --callbackUrl="https://foourl"
8 *   --description="Application description"
9 *   --grants="editprotected"
10 *   --grants="createaccount"
11 *   --name="Application name"
12 *   --user="Admin"
13 *   --version="0.2"
14 *   --wiki=default
15 *   --approve
16 *
17 * You can optionally output successful results as json using --jsonOnSuccess
18 */
19
20namespace MediaWiki\Extension\OAuth;
21
22use Maintenance;
23use MediaWiki\Extension\OAuth\Backend\Consumer;
24use MediaWiki\Extension\OAuth\Backend\Utils;
25use MediaWiki\Extension\OAuth\Control\ConsumerSubmitControl;
26use MediaWiki\User\User;
27use MWRestrictions;
28use RequestContext;
29
30/**
31 * @ingroup Maintenance
32 */
33
34if ( getenv( 'MW_INSTALL_PATH' ) ) {
35    $IP = getenv( 'MW_INSTALL_PATH' );
36} else {
37    $IP = __DIR__ . '/../../..';
38}
39
40require_once "$IP/maintenance/Maintenance.php";
41
42class CreateOAuthConsumer extends Maintenance {
43    public function __construct() {
44        parent::__construct();
45        $this->addDescription( "Create an OAuth consumer" );
46        $this->addOption( 'user', 'User to run the script as', true, true );
47        $this->addOption( 'name', 'Application name', true, true );
48        $this->addOption( 'description', 'Application description', true, true );
49        $this->addOption( 'version', 'Application version', true, true );
50        $this->addOption( 'callbackUrl', 'Callback URL', true, true );
51        $this->addOption(
52            'callbackIsPrefix',
53            'Allow a consumer to specify a callback in requests',
54            true
55        );
56        $this->addOption( 'grants', 'Grants', true, true, false, true );
57        $this->addOption( 'jsonOnSuccess', 'Output successful results as JSON' );
58        $this->addOption( 'approve', 'Accept the consumer' );
59        $this->requireExtension( "OAuth" );
60    }
61
62    public function execute() {
63        $user = User::newFromName( $this->getOption( 'user' ) );
64        if ( !$user->isNamed() ) {
65            $this->fatalError( 'User must be registered' );
66        }
67        if ( $user->getEmail() === '' ) {
68            $this->fatalError( 'User must have an email' );
69        }
70
71        $data = [
72            'action' => 'propose',
73            'name'         => $this->getOption( 'name' ),
74            'version'      => $this->getOption( 'version' ),
75            'description'  => $this->getOption( 'description' ),
76            'callbackUrl'  => $this->getOption( 'callbackUrl' ),
77            'oauthVersion' => 1,
78            'callbackIsPrefix' => $this->hasOption( 'callbackIsPrefix' ),
79            'grants' => '["' . implode( '","', $this->getOption( 'grants' ) ) . '"]',
80            'granttype' => 'normal',
81            'ownerOnly' => false,
82            // Only support OAuth 1 for now, but that requires valid values for OAuth 2 fields
83            'oauth2IsConfidential' => true,
84            'oauth2GrantTypes' => [ 'authorization_code', 'refresh_token' ],
85            'email' => $user->getEmail(),
86            // All wikis
87            'wiki' => '*',
88            // Generate a key
89            'rsaKey' => '',
90            'agreement' => true,
91            'restrictions' => MWRestrictions::newDefault(),
92        ];
93
94        $context = RequestContext::getMain();
95        $context->setUser( $user );
96
97        $dbw = Utils::getCentralDB( DB_PRIMARY );
98        $control = new ConsumerSubmitControl( $context, $data, $dbw );
99        $status = $control->submit();
100
101        if ( !$status->isGood() ) {
102            $this->fatalError( $status->getMessage()->text() );
103        }
104
105        /** @var Consumer $cmr */
106        // @phan-suppress-next-line PhanTypeArraySuspiciousNullable
107        $cmr = $status->value['result']['consumer'];
108
109        if ( $this->hasOption( 'approve' ) ) {
110            $data = [
111                'action' => 'approve',
112                'consumerKey'  => $cmr->getConsumerKey(),
113                'reason'       => 'Approved by maintenance script',
114                'changeToken'  => $cmr->getChangeToken( $context ),
115            ];
116            $control = new ConsumerSubmitControl( $context, $data, $dbw );
117            $approveStatus = $control->submit();
118        }
119
120        $outputData = [
121            'created' => true,
122            'id' => $cmr->getId(),
123            'name' => $cmr->getName(),
124            'key' => $cmr->getConsumerKey(),
125            'secret' => Utils::hmacDBSecret( $cmr->getSecretKey() ),
126        ];
127
128        if ( isset( $approveStatus ) ) {
129            $outputData['approved'] = $approveStatus->isGood() ?
130                1 : $approveStatus->getWikiText( false, false, 'en' );
131        }
132
133        if ( $this->hasOption( 'jsonOnSuccess' ) ) {
134            $this->output( json_encode( $outputData ) );
135        } else {
136            foreach ( $outputData as $key => $value ) {
137                $this->output( $key . ': ' . $value . PHP_EOL );
138            }
139        }
140    }
141}
142
143$maintClass = CreateOAuthConsumer::class;
144require_once RUN_MAINTENANCE_IF_MAIN;