mediawiki-extensions-OATHAuth/OATHAuth.hooks.php
Tyler Anthony Romeo 0c389f5025 Refactored special pages into HTMLForm and proxy
Made new class ProxySpecialPage, which acts as a
proxy object to another SpecialPage object that is
determined based on context information other than
the title.

Then Special:OATH has been split into two separate
special page classes (both FormSpecialPages using
HTMLForm) that are routed to by a ProxySpecialPage
object.

In addition, the form for enabling two-factor auth
has been refactored into vform style, with some
better instructions on how to enable two-factor
authentication.

Change-Id: Ib9117cbc9d7f044de9607db81a157e1b472b5ec0
2016-03-23 11:26:04 -07:00

212 lines
5.1 KiB
PHP

<?php
/**
* Hooks for Extension:OATHAuth
*
* @ingroup Extensions
*/
class OATHAuthHooks {
/**
* @param $template UserloginTemplate
* @return bool
*/
static function ModifyUITemplate( &$template ) {
$input = '<div><label for="wpOATHToken">'
. wfMessage( 'oathauth-token' )->escaped()
. '</label>'
. Html::input( 'wpOATHToken', null, 'text', array(
'class' => 'loginText', 'id' => 'wpOATHToken', 'tabindex' => '3', 'size' => '20'
) ) . '</div>';
$template->set( 'extrafields', $template->get( 'extrafields', '' ) . $input );
return true;
}
/**
* @param $extraFields array
* @return bool
*/
static function ChangePasswordForm( &$extraFields ) {
$tokenField = array( 'wpOATHToken', 'oathauth-token', 'password', '' );
array_push( $extraFields, $tokenField );
return true;
}
/**
* @param $user User
* @param $password string
* @param $newpassword string
* @param &$errorMsg string
* @return bool
*/
static function AbortChangePassword( $user, $password, $newpassword, &$errorMsg ) {
$result = self::authenticate( $user );
if ( $result ) {
return true;
} else {
$errorMsg = 'oathauth-abortlogin';
return false;
}
}
/**
* @param $user User
* @param $password string
* @param &$abort int
* @param &$errorMsg string
* @return bool
*/
static function AbortLogin( $user, $password, &$abort, &$errorMsg ) {
$result = self::authenticate( $user );
if ( $result ) {
return true;
} else {
$abort = LoginForm::ABORTED;
$errorMsg = 'oathauth-abortlogin';
return false;
}
}
/**
* @param $user User
* @return bool
*/
static function authenticate( $user ) {
global $wgRequest;
$token = $wgRequest->getText( 'wpOATHToken' );
$oathrepo = new OATHUserRepository( wfGetLB() );
$oathuser = $oathrepo->findByUser( $user );
# Though it's weird to default to true, we only want to deny
# users who have two-factor enabled and have validated their
# token.
$result = true;
if ( $oathuser->getKey() !== null ) {
$result = $oathuser->getKey()->verifyToken( $token, $oathuser );
}
return $result;
}
/**
* Determine if two-factor authentication is enabled for $wgUser
*
* @param bool &$isEnabled Will be set to true if enabled, false otherwise
*
* @return bool False if enabled, true otherwise
*/
static function TwoFactorIsEnabled( &$isEnabled ) {
global $wgUser;
$oathrepo = new OATHUserRepository( wfGetLB() );
$user = $oathrepo->findByUser( $wgUser );
if ( $user && $user->getKey() !== null ) {
$isEnabled = true;
# This two-factor extension is enabled by the user,
# we don't need to check others.
return false;
} else {
$isEnabled = false;
# This two-factor extension isn't enabled by the user,
# but others may be.
return true;
}
}
/**
* Add the necessary user preferences for OATHAuth
*
* @param User $user
* @param array $preferences
*
* @return bool
*/
public static function manageOATH( User $user, array &$preferences ) {
$oathrepo = new OATHUserRepository( wfGetLB() );
$oathUser = $oathrepo->findByUser( $user );
$title = SpecialPage::getTitleFor( 'OATH' );
$msg = $oathUser->getKey() !== null ? 'oathauth-disable' : 'oathauth-enable';
$preferences[$msg] = array(
'type' => 'info',
'raw' => 'true',
'default' => Linker::link(
$title,
wfMessage( $msg )->escaped(),
array(),
array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() )
),
'label-message' => 'oathauth-prefs-label',
'section' => 'personal/info',
);
return true;
}
/**
* @param DatabaseUpdater $updater
* @return bool
*/
public static function OATHAuthSchemaUpdates( $updater ) {
$base = dirname( __FILE__ );
switch ( $updater->getDB()->getType() ) {
case 'mysql':
case 'sqlite':
$updater->addExtensionTable( 'oathauth_users', "$base/sql/mysql/tables.sql" );
$updater->addExtensionUpdate( array( array( __CLASS__, 'schemaUpdateOldUsersFromInstaller' ) ) );
$updater->dropExtensionField( 'oathauth_users', 'secret_reset',
"$base/sql/mysql/patch-remove_reset.sql" );
break;
}
return true;
}
/**
* Helper function for converting old users to the new schema
* @see OATHAuthHooks::OATHAuthSchemaUpdates
*
* @param DatabaseUpdater $updater
*
* @return bool
*/
public static function schemaUpdateOldUsersFromInstaller( DatabaseUpdater $updater ) {
return self::schemaUpdateOldUsers($updater->getDB());
}
/**
* Helper function for converting old users to the new schema
* @see OATHAuthHooks::OATHAuthSchemaUpdates
*
* @param DatabaseUpdater $updater
*
* @return bool
*/
public static function schemaUpdateOldUsers( DatabaseBase $db ) {
if ( !$db->fieldExists( 'oathauth_users', 'secret_reset' ) ) {
return true;
}
$res = $db->select( 'oathauth_users', array( 'id', 'scratch_tokens' ), '', __METHOD__ );
foreach ( $res as $row ) {
$scratchTokens = unserialize( base64_decode( $row->scratch_tokens ) );
if ( $scratchTokens ) {
$db->update(
'oathauth_users',
array( 'scratch_tokens' => implode( ',', $scratchTokens ) ),
array( 'id' => $row->id ),
__METHOD__
);
}
}
return true;
}
}