Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
+121
-97
@@ -11,16 +11,36 @@
|
||||
namespace IPS\MFA;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DateInterval;
|
||||
use IPS\Application;
|
||||
use IPS\DateTime;
|
||||
use IPS\Db;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\Verify\Handler;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use const IPS\DEV_FORCE_MFA;
|
||||
use const IPS\DISABLE_MFA;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract Multi Factor Authentication Handler and Factory
|
||||
*/
|
||||
abstract class _MFAHandler
|
||||
abstract class MFAHandler
|
||||
{
|
||||
/* !Access Methods */
|
||||
|
||||
@@ -29,10 +49,10 @@ abstract class _MFAHandler
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function areas()
|
||||
public static function areas(): array
|
||||
{
|
||||
$return = array();
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'MFAArea', FALSE, 'core', NULL, FALSE ) as $k => $v )
|
||||
foreach ( Application::allExtensions( 'core', 'MFAArea', FALSE, 'core', NULL, FALSE ) as $k => $v )
|
||||
{
|
||||
$return[ $k ] = "MFA_{$k}";
|
||||
}
|
||||
@@ -44,13 +64,13 @@ abstract class _MFAHandler
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function handlers()
|
||||
public static function handlers(): array
|
||||
{
|
||||
return array(
|
||||
'authy' => new \IPS\MFA\Authy\Handler(),
|
||||
'google' => new \IPS\MFA\GoogleAuthenticator\Handler(),
|
||||
'questions' => new \IPS\MFA\SecurityQuestions\Handler(),
|
||||
'verify' => new \IPS\MFA\Verify\Handler()
|
||||
'authy' => new Authy\Handler(),
|
||||
'google' => new GoogleAuthenticator\Handler(),
|
||||
'questions' => new SecurityQuestions\Handler(),
|
||||
'verify' => new Handler()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,7 +79,7 @@ abstract class _MFAHandler
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function resetAuthentication()
|
||||
public static function resetAuthentication() : void
|
||||
{
|
||||
if ( isset( $_SESSION['MFAAuthenticated'] ) )
|
||||
{
|
||||
@@ -70,44 +90,44 @@ abstract class _MFAHandler
|
||||
/**
|
||||
* Display output when trying to access an area
|
||||
*
|
||||
* @param string $app The application which owns the MFAArea extension
|
||||
* @param string $area The MFAArea key
|
||||
* @param \IPS\Http\Url $url URL for page
|
||||
* @param \IPS\Member $member The member, or NULL for currently logged in member
|
||||
* @return string
|
||||
* @param string $app The application which owns the MFAArea extension
|
||||
* @param string $area The MFAArea key
|
||||
* @param Url $url URL for page
|
||||
* @param Member|null $member The member, or NULL for currently logged in member
|
||||
* @return string|null
|
||||
*/
|
||||
public static function accessToArea( $app, $area, \IPS\Http\Url $url, \IPS\Member $member = NULL )
|
||||
public static function accessToArea( string $app, string $area, Url $url, ?Member $member = NULL ): ?string
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$member = $member ?: Member::loggedIn();
|
||||
|
||||
/* Constant to disable MFA for emergency recovery */
|
||||
if ( \IPS\DISABLE_MFA )
|
||||
if ( DISABLE_MFA )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If MFA is not enabled for this area, do nothing */
|
||||
if ( !\IPS\Settings::i()->security_questions_areas or !\in_array( "{$app}_{$area}", explode( ',', \IPS\Settings::i()->security_questions_areas ) ) )
|
||||
if ( !Settings::i()->security_questions_areas or !in_array( "{$app}_{$area}", explode( ',', Settings::i()->security_questions_areas ) ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Are we already authenticated? */
|
||||
if ( !\IPS\DEV_FORCE_MFA and ( isset( $_SESSION['MFAAuthenticated'] ) and ( !\IPS\Settings::i()->security_questions_timer or ( ( $_SESSION['MFAAuthenticated'] + ( \IPS\Settings::i()->security_questions_timer * 60 ) ) > time() ) ) ) )
|
||||
if ( !DEV_FORCE_MFA and ( isset( $_SESSION['MFAAuthenticated'] ) and ( !Settings::i()->security_questions_timer or ( ( $_SESSION['MFAAuthenticated'] + ( Settings::i()->security_questions_timer * 60 ) ) > time() ) ) ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* "Opt Out" */
|
||||
if ( \IPS\Settings::i()->mfa_required_groups != '*' and !$member->inGroup( explode( ',', \IPS\Settings::i()->mfa_required_groups ) ) )
|
||||
if ( Settings::i()->mfa_required_groups != '*' and !$member->inGroup( explode( ',', Settings::i()->mfa_required_groups ) ) )
|
||||
{
|
||||
if ( $member->members_bitoptions['security_questions_opt_out'] )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->_mfa ) and \IPS\Request::i()->_mfa == 'optout' )
|
||||
if ( isset( Request::i()->_mfa ) and Request::i()->_mfa == 'optout' )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
$member->members_bitoptions['security_questions_opt_out'] = TRUE;
|
||||
$member->save();
|
||||
@@ -137,15 +157,15 @@ abstract class _MFAHandler
|
||||
/* Locked out? */
|
||||
if ( $lockedOutScreen = static::_lockedOutScreen( $member ) )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
return $lockedOutScreen;
|
||||
}
|
||||
|
||||
/* "Try another way to sign in" */
|
||||
if ( isset( \IPS\Request::i()->_mfa ) )
|
||||
if ( isset( Request::i()->_mfa ) )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
if ( \IPS\Request::i()->_mfa == 'alt' )
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
if ( Request::i()->_mfa == 'alt' )
|
||||
{
|
||||
/* What handlers have we configured? */
|
||||
$configuredHandlers = array();
|
||||
@@ -157,26 +177,26 @@ abstract class _MFAHandler
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->_mfaMethod ) and array_key_exists( \IPS\Request::i()->_mfaMethod, $configuredHandlers ) )
|
||||
if ( isset( Request::i()->_mfaMethod ) and array_key_exists( Request::i()->_mfaMethod, $configuredHandlers ) )
|
||||
{
|
||||
return static::_showHandlerAuthScreen( $configuredHandlers[ \IPS\Request::i()->_mfaMethod ], $url->setQueryString( array( '_mfa' => 'alt', '_mfaMethod' => \IPS\Request::i()->_mfaMethod ) ), $member );
|
||||
return static::_showHandlerAuthScreen( $configuredHandlers[ Request::i()->_mfaMethod ], $url->setQueryString( array( '_mfa' => 'alt', '_mfaMethod' => Request::i()->_mfaMethod ) ), $member );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$knownDevicesAvailable = FALSE;
|
||||
if ( $app === 'core' and $area === 'AuthenticateFront' and !\in_array( "app_AuthenticateFrontKnown", explode( ',', \IPS\Settings::i()->security_questions_areas ) ) )
|
||||
if ( $app === 'core' and $area === 'AuthenticateFront' and !in_array( "app_AuthenticateFrontKnown", explode( ',', Settings::i()->security_questions_areas ) ) )
|
||||
{
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_members_known_devices', array( 'member_id=?', $member->member_id ) )->first() )
|
||||
if ( Db::i()->select( 'COUNT(*)', 'core_members_known_devices', array( 'member_id=?', $member->member_id ) )->first() )
|
||||
{
|
||||
$knownDevicesAvailable = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaRecovery( $configuredHandlers, $url, $knownDevicesAvailable );
|
||||
return Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaRecovery( $configuredHandlers, $url, $knownDevicesAvailable );
|
||||
}
|
||||
elseif ( \IPS\Request::i()->_mfa == 'knownDevice' )
|
||||
elseif ( Request::i()->_mfa == 'knownDevice' )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'system', 'core' )->mfaKnownDeviceInfo( $url );
|
||||
return Theme::i()->getTemplate( 'system', 'core' )->mfaKnownDeviceInfo( $url );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,24 +205,24 @@ abstract class _MFAHandler
|
||||
{
|
||||
if ( $handler->memberHasConfiguredHandler( $member ) )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
return static::_showHandlerAuthScreen( $handler, $url, $member );
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup form */
|
||||
$showSetupForm = ( \IPS\Settings::i()->mfa_required_groups == '*' or $member->inGroup( explode( ',', \IPS\Settings::i()->mfa_required_groups ) ) ) ? 'mfa_required_prompt' : 'mfa_optional_prompt';
|
||||
if ( \IPS\Settings::i()->$showSetupForm === 'access' or ( $app === 'core' and $area === 'AuthenticateAdmin' and \IPS\Settings::i()->$showSetupForm === 'immediate' ) )
|
||||
$showSetupForm = ( Settings::i()->mfa_required_groups == '*' or $member->inGroup( explode( ',', Settings::i()->mfa_required_groups ) ) ) ? 'mfa_required_prompt' : 'mfa_optional_prompt';
|
||||
if ( Settings::i()->$showSetupForm === 'access' or ( $app === 'core' and $area === 'AuthenticateAdmin' and Settings::i()->$showSetupForm === 'immediate' ) )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
|
||||
/* Did we just submit it? */
|
||||
if ( isset( \IPS\Request::i()->mfa_setup ) and isset( \IPS\Request::i()->csrfKey ) )
|
||||
if ( isset( Request::i()->mfa_setup ) and isset( Request::i()->csrfKey ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
foreach ( $acceptableHandlers as $key => $handler )
|
||||
{
|
||||
if ( ( \count( $acceptableHandlers ) == 1 ) or $key == \IPS\Request::i()->mfa_method )
|
||||
if ( ( count( $acceptableHandlers ) == 1 ) or $key == Request::i()->mfa_method )
|
||||
{
|
||||
if ( $handler->configurationScreenSubmit( $member ) )
|
||||
{
|
||||
@@ -218,24 +238,26 @@ abstract class _MFAHandler
|
||||
}
|
||||
|
||||
/* No, show it */
|
||||
return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaSetup( $acceptableHandlers, $member, $url );
|
||||
return Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaSetup( $acceptableHandlers, $member, $url );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a handler's authentication screen
|
||||
*
|
||||
* @param \IPS\MFA\MFAHandler $handler The handler to use
|
||||
* @param \IPS\Http\Url $url URL for page
|
||||
* @param \IPS\Member $member The member
|
||||
* @param MFAHandler $handler The handler to use
|
||||
* @param Url $url URL for page
|
||||
* @param Member $member The member
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function _showHandlerAuthScreen( \IPS\MFA\MFAHandler $handler, \IPS\Http\Url $url, \IPS\Member $member )
|
||||
protected static function _showHandlerAuthScreen( MFAHandler $handler, Url $url, Member $member ): ?string
|
||||
{
|
||||
/* Did we just submit it? */
|
||||
if ( isset( \IPS\Request::i()->mfa_auth ) )
|
||||
if ( isset( Request::i()->mfa_auth ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
if ( $handler->authenticationScreenSubmit( $member ) )
|
||||
{
|
||||
$member->failed_mfa_attempts = 0;
|
||||
@@ -248,25 +270,25 @@ abstract class _MFAHandler
|
||||
$member->failed_mfa_attempts++;
|
||||
$member->save();
|
||||
|
||||
\IPS\Request::i()->mfa_auth = NULL;
|
||||
Request::i()->mfa_auth = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* No, show it */
|
||||
return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaAuthenticate( $handler->authenticationScreen( $member, $url ), $url );
|
||||
return Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaAuthenticate( $handler->authenticationScreen( $member, $url ), $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the locked out screen, if necessary
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param Member $member The member
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function _lockedOutScreen( \IPS\Member $member )
|
||||
protected static function _lockedOutScreen( Member $member ): ?string
|
||||
{
|
||||
if ( $member->failed_mfa_attempts >= \IPS\Settings::i()->security_questions_tries )
|
||||
if ( $member->failed_mfa_attempts >= Settings::i()->security_questions_tries )
|
||||
{
|
||||
if ( \IPS\Settings::i()->mfa_lockout_behaviour == 'lock' )
|
||||
if ( Settings::i()->mfa_lockout_behaviour == 'lock' )
|
||||
{
|
||||
$mfaDetails = $member->mfa_details;
|
||||
if ( !isset( $mfaDetails['_lockouttime'] ) )
|
||||
@@ -275,10 +297,10 @@ abstract class _MFAHandler
|
||||
$member->mfa_details = $mfaDetails;
|
||||
$member->save();
|
||||
|
||||
$member->logHistory( 'core', 'login', array( 'type' => 'mfalock', 'count' => $member->failed_mfa_attempts, 'unlockTime' => \IPS\DateTime::create()->add( new \DateInterval( 'PT' . \IPS\Settings::i()->mfa_lockout_time . 'M' ) )->getTimestamp() ) );
|
||||
$member->logHistory( 'core', 'login', array( 'type' => 'mfalock', 'count' => $member->failed_mfa_attempts, 'unlockTime' => DateTime::create()->add( new DateInterval( 'PT' . Settings::i()->mfa_lockout_time . 'M' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
$lockEndTime = \IPS\DateTime::ts( $mfaDetails['_lockouttime'] )->add( new \DateInterval( 'PT' . \IPS\Settings::i()->mfa_lockout_time . 'M' ) );
|
||||
$lockEndTime = DateTime::ts( $mfaDetails['_lockouttime'] )->add( new DateInterval( 'PT' . Settings::i()->mfa_lockout_time . 'M' ) );
|
||||
if ( $lockEndTime->getTimestamp() < time() )
|
||||
{
|
||||
unset( $mfaDetails['_lockouttime'] );
|
||||
@@ -288,18 +310,20 @@ abstract class _MFAHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaLockout( ( \IPS\Settings::i()->mfa_lockout_time > 1440 ) ? $lockEndTime : $lockEndTime->localeTime( FALSE ) );
|
||||
return Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaLockout( ( Settings::i()->mfa_lockout_time > 1440 ) ? $lockEndTime : $lockEndTime->localeTime( FALSE ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $member->failed_mfa_attempts == \IPS\Settings::i()->security_questions_tries )
|
||||
if ( $member->failed_mfa_attempts == Settings::i()->security_questions_tries )
|
||||
{
|
||||
$member->logHistory( 'core', 'login', array( 'type' => 'mfalock', 'count' => $member->failed_mfa_attempts ) );
|
||||
}
|
||||
return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaLockout();
|
||||
return Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaLockout();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* !Setup */
|
||||
@@ -309,89 +333,89 @@ abstract class _MFAHandler
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function isEnabled();
|
||||
abstract public function isEnabled(): bool;
|
||||
|
||||
/**
|
||||
* Member *can* use this handler (even if they have not yet configured it)
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param Member $member The member
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function memberCanUseHandler( \IPS\Member $member );
|
||||
abstract public function memberCanUseHandler( Member $member ): bool;
|
||||
|
||||
/**
|
||||
* Member has configured this handler
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param Member $member The member
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function memberHasConfiguredHandler( \IPS\Member $member );
|
||||
abstract public function memberHasConfiguredHandler( Member $member ): bool;
|
||||
|
||||
/**
|
||||
* Show a setup screen
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param bool $showingMultipleHandlers Set to TRUE if multiple options are being displayed
|
||||
* @param \IPS\Http\Url $url URL for page
|
||||
* @param Member $member The member
|
||||
* @param bool $showingMultipleHandlers Set to TRUE if multiple options are being displayed
|
||||
* @param Url $url URL for page
|
||||
* @return string
|
||||
*/
|
||||
abstract public function configurationScreen( \IPS\Member $member, $showingMultipleHandlers, \IPS\Http\Url $url );
|
||||
abstract public function configurationScreen( Member $member, bool $showingMultipleHandlers, Url $url ): string;
|
||||
|
||||
/**
|
||||
* Submit configuration screen. Return TRUE if was accepted
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param Member $member The member
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function configurationScreenSubmit( \IPS\Member $member );
|
||||
abstract public function configurationScreenSubmit( Member $member ): bool;
|
||||
|
||||
/* !Authentication */
|
||||
|
||||
/**
|
||||
* Get the form for a member to authenticate
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param \IPS\Http\Url $url URL for page
|
||||
* @param Member $member The member
|
||||
* @param Url $url URL for page
|
||||
* @return string
|
||||
*/
|
||||
abstract public function authenticationScreen( \IPS\Member $member, \IPS\Http\Url $url );
|
||||
abstract public function authenticationScreen( Member $member, Url $url ): string;
|
||||
|
||||
/**
|
||||
* Submit authentication screen. Return TRUE if was accepted
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @return string
|
||||
* @param Member $member The member
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function authenticationScreenSubmit( \IPS\Member $member );
|
||||
abstract public function authenticationScreenSubmit( Member $member ): bool;
|
||||
|
||||
/* !ACP */
|
||||
|
||||
/**
|
||||
* Toggle
|
||||
*
|
||||
* @param bool $enabled On/Off
|
||||
* @return bool
|
||||
* @param bool $enabled On/Off
|
||||
* @return void
|
||||
*/
|
||||
abstract public function toggle( $enabled );
|
||||
abstract public function toggle( bool $enabled ) : void;
|
||||
|
||||
/**
|
||||
* ACP Settings
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function acpSettings();
|
||||
abstract public function acpSettings(): string;
|
||||
|
||||
/**
|
||||
* Configuration options when editing member account in ACP
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param Member $member The member
|
||||
* @return array
|
||||
*/
|
||||
public function acpConfiguration( \IPS\Member $member )
|
||||
public function acpConfiguration( Member $member ): array
|
||||
{
|
||||
if ( $this->memberHasConfiguredHandler( $member ) )
|
||||
{
|
||||
return array( new \IPS\Helpers\Form\YesNo( "mfa_{$this->key}_title", $this->memberHasConfiguredHandler( $member ), FALSE, array(), NULL, NULL, NULL, "mfa_{$this->key}_title" ) );
|
||||
return array( new YesNo( "mfa_{$this->key}_title", $this->memberHasConfiguredHandler( $member ), FALSE, array(), NULL, NULL, NULL, "mfa_{$this->key}_title" ) );
|
||||
}
|
||||
return array();
|
||||
}
|
||||
@@ -399,11 +423,11 @@ abstract class _MFAHandler
|
||||
/**
|
||||
* Save configuration when editing member account in ACP
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param array $values Values from form
|
||||
* @return array
|
||||
* @param Member $member The member
|
||||
* @param array $values Values from form
|
||||
* @return void
|
||||
*/
|
||||
public function acpConfigurationSave( \IPS\Member $member, $values )
|
||||
public function acpConfigurationSave(Member $member, array $values ) : void
|
||||
{
|
||||
if ( isset( $values["mfa_{$this->key}_title"] ) and !$values["mfa_{$this->key}_title"] )
|
||||
{
|
||||
@@ -419,19 +443,19 @@ abstract class _MFAHandler
|
||||
/**
|
||||
* If member has configured this handler, disable it
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @return bool
|
||||
* @param Member $member The member
|
||||
* @return void
|
||||
*/
|
||||
abstract public function disableHandlerForMember( \IPS\Member $member );
|
||||
abstract public function disableHandlerForMember( Member $member ) : void;
|
||||
|
||||
/**
|
||||
* Get title for UCP
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ucpTitle()
|
||||
public function ucpTitle(): string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack("mfa_{$this->key}_title");
|
||||
return Member::loggedIn()->language()->addToStack("mfa_{$this->key}_title");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -439,9 +463,9 @@ abstract class _MFAHandler
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ucpDesc()
|
||||
public function ucpDesc(): string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack("mfa_{$this->key}_desc_user");
|
||||
return Member::loggedIn()->language()->addToStack("mfa_{$this->key}_desc_user");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -449,9 +473,9 @@ abstract class _MFAHandler
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function recoveryButton()
|
||||
public function recoveryButton(): string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack("mfa_recovery_{$this->key}");
|
||||
return Member::loggedIn()->language()->addToStack("mfa_recovery_{$this->key}");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user