Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 67
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
VerifyOATHForUser
0.00% covered (danger)
0.00%
0 / 67
0.00% covered (danger)
0.00%
0 / 12
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doesWrites
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLoginSecurityLevel
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 alterForm
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getDisplayFormat
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 requiresUnblock
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkExecutePermissions
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getFormFields
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 onSubmit
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
30
 onSuccess
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace MediaWiki\Extension\OATHAuth\Special;
4
5use ManualLogEntry;
6use MediaWiki\CheckUser\Hooks as CheckUserHooks;
7use MediaWiki\Config\ConfigException;
8use MediaWiki\Extension\OATHAuth\OATHUserRepository;
9use MediaWiki\HTMLForm\HTMLForm;
10use MediaWiki\Logger\LoggerFactory;
11use MediaWiki\Registration\ExtensionRegistry;
12use MediaWiki\SpecialPage\FormSpecialPage;
13use MediaWiki\User\User;
14use MediaWiki\User\UserFactory;
15use MWException;
16use UserBlockedError;
17use UserNotLoggedIn;
18
19class VerifyOATHForUser extends FormSpecialPage {
20
21    private const OATHAUTH_IS_ENABLED = 'enabled';
22    private const OATHAUTH_NOT_ENABLED = 'disabled';
23    private OATHUserRepository $userRepo;
24    private UserFactory $userFactory;
25
26    /** @var string */
27    private $enabledStatus;
28
29    /** @var string */
30    private $targetUser;
31
32    /**
33     * @param OATHUserRepository $userRepo
34     * @param UserFactory $userFactory
35     */
36    public function __construct( $userRepo, $userFactory ) {
37        // messages used: verifyoathforuser (display "name" on Special:SpecialPages),
38        // right-oathauth-verify-user, action-oathauth-verify-user
39        parent::__construct( 'VerifyOATHForUser', 'oathauth-verify-user' );
40        $this->userRepo = $userRepo;
41        $this->userFactory = $userFactory;
42    }
43
44    /**
45     * @inheritDoc
46     */
47    protected function getGroupName() {
48        return 'users';
49    }
50
51    public function doesWrites() {
52        return true;
53    }
54
55    /**
56     * @return string
57     */
58    protected function getLoginSecurityLevel() {
59        return $this->getName();
60    }
61
62    /**
63     * @param HTMLForm $form
64     */
65    public function alterForm( HTMLForm $form ) {
66        $form->setMessagePrefix( 'oathauth' );
67        $form->getOutput()->setPageTitleMsg( $this->msg( 'oathauth-verify-for-user' ) );
68    }
69
70    /**
71     * @return string
72     */
73    protected function getDisplayFormat() {
74        return 'ooui';
75    }
76
77    /**
78     * @return bool
79     */
80    public function requiresUnblock() {
81        return true;
82    }
83
84    /**
85     * @param User $user
86     * @throws UserBlockedError
87     * @throws UserNotLoggedIn
88     */
89    protected function checkExecutePermissions( User $user ) {
90        $this->requireNamedUser();
91
92        parent::checkExecutePermissions( $user );
93    }
94
95    /**
96     * @param string $par
97     */
98    public function execute( $par ) {
99        $this->getOutput()->disallowUserJs();
100        parent::execute( $par );
101    }
102
103    /**
104     * @return array[]
105     */
106    protected function getFormFields() {
107        return [
108            'user' => [
109                'type' => 'user',
110                'default' => '',
111                'label-message' => 'oathauth-enteruser',
112                'name' => 'user',
113                'required' => true,
114                'excludetemp' => true,
115            ],
116            'reason' => [
117                'type' => 'text',
118                'default' => '',
119                'label-message' => 'oathauth-enterverifyreason',
120                'name' => 'reason',
121                'required' => true,
122            ],
123        ];
124    }
125
126    /**
127     * @param array $formData
128     * @return array|true
129     * @throws ConfigException
130     * @throws MWException
131     */
132    public function onSubmit( array $formData ) {
133        $this->targetUser = $formData['user'];
134        $user = $this->userFactory->newFromName( $this->targetUser );
135        if ( !$user || $user->getId() === 0 ) {
136            return [ 'oathauth-user-not-found' ];
137        }
138        $oathUser = $this->userRepo->findByUser( $user );
139
140        $this->enabledStatus = $oathUser->isTwoFactorAuthEnabled()
141            ? self::OATHAUTH_IS_ENABLED
142            : self::OATHAUTH_NOT_ENABLED;
143
144        // messages used: logentry-oath-verify, log-action-oath-verify
145        $logEntry = new ManualLogEntry( 'oath', 'verify' );
146        $logEntry->setPerformer( $this->getUser() );
147        $logEntry->setTarget( $user->getUserPage() );
148        $logEntry->setComment( $formData['reason'] );
149        $logEntry->insert();
150
151        if ( ExtensionRegistry::getInstance()->isLoaded( 'CheckUser' ) ) {
152            CheckUserHooks::updateCheckUserData( $logEntry->getRecentChange() );
153        }
154
155        LoggerFactory::getInstance( 'authentication' )->info(
156            'OATHAuth status checked for {usertarget} by {user} from {clientip}', [
157                'user' => $this->getUser()->getName(),
158                'usertarget' => $this->targetUser,
159                'clientip' => $this->getRequest()->getIP(),
160            ]
161        );
162
163        return true;
164    }
165
166    /**
167     * @throws MWException
168     */
169    public function onSuccess() {
170        switch ( $this->enabledStatus ) {
171            case self::OATHAUTH_IS_ENABLED:
172                $msg = 'oathauth-verify-enabled';
173                break;
174            case self::OATHAUTH_NOT_ENABLED:
175                $msg = 'oathauth-verify-disabled';
176                break;
177            default:
178                throw new MWException(
179                    'Verification was successful but status is unknown'
180                );
181        }
182
183        $out = $this->getOutput();
184        $out->addBacklinkSubtitle( $this->getPageTitle() );
185        $out->addWikiMsg( $msg, $this->targetUser );
186    }
187
188}