move backup codes to separate db table, clear backup code if used or new codes are generated

Cette révision appartient à :
Daniel Seifert 2019-07-28 23:00:30 +02:00
Parent 2e9fca06c0
révision a42121b4bc
10 fichiers modifiés avec 348 ajouts et 163 suppressions

Voir le fichier

@ -1,19 +1,23 @@
CREATE TABLE `d3totp` ( CREATE TABLE IF NOT EXISTS `d3totp` (
`OXID` CHAR(32) NOT NULL, `OXID` CHAR(32) NOT NULL ,
`OXUSERID` CHAR(32) NOT NULL, `OXUSERID` CHAR(32) NOT NULL ,
`USETOTP` TINYINT(1) NOT NULL DEFAULT '0', `USETOTP` TINYINT(1) NOT NULL DEFAULT 0,
`SEED` VARCHAR(256) NOT NULL DEFAULT '0', `SEED` VARCHAR(256) NOT NULL ,
`BC1` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #1', `OXTIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
`BC2` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #2', PRIMARY KEY (`OXID`) ,
`BC3` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #3', UNIQUE KEY `OXUSERID` (`OXUSERID`)
`BC4` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #4', )
`BC5` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #5', ENGINE=InnoDB
`BC6` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #6', COMMENT='totp setting';
`BC7` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #7',
`BC8` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #8', CREATE TABLE IF NOT EXISTS `d3totp_backupcodes` (
`BC9` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #9', `OXID` CHAR(32) NOT NULL ,
`BC10` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT 'BackupCode #10', `OXUSERID` CHAR(32) NOT NULL COMMENT 'user id',
PRIMARY KEY (`OXID`), `BACKUPCODE` VARCHAR(64) NOT NULL COMMENT 'BackupCode',
UNIQUE INDEX `OXUSERID` (`OXUSERID`) `OXTIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
) PRIMARY KEY (`OXID`) ,
KEY `OXUSERID` (`OXUSERID`) ,
KEY `BACKUPCODE` (`BACKUPCODE`)
)
ENGINE=InnoDB ENGINE=InnoDB
COMMENT='totp backup codes';

Voir le fichier

@ -1 +1 @@
# no update instructions available # no update instructions available

Voir le fichier

@ -16,11 +16,11 @@
namespace D3\Totp\Application\Controller\Admin; namespace D3\Totp\Application\Controller\Admin;
use D3\Totp\Application\Model\d3totp; use D3\Totp\Application\Model\d3totp;
use D3\Totp\Application\Model\Exceptions\d3backupcodelist;
use D3\Totp\Modules\Application\Model\d3_totp_user; use D3\Totp\Modules\Application\Model\d3_totp_user;
use Doctrine\DBAL\DBALException; use Exception;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController; use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
@ -30,10 +30,10 @@ class d3user_totp extends AdminDetailsController
protected $_sThisTemplate = 'd3user_totp.tpl'; protected $_sThisTemplate = 'd3user_totp.tpl';
public $aBackupCodes = array();
/** /**
* @return string * @return string
* @throws DBALException
* @throws DatabaseConnectionException
*/ */
public function render() public function render()
{ {
@ -60,7 +60,7 @@ class d3user_totp extends AdminDetailsController
} }
/** /**
* @throws \Exception * @throws Exception
*/ */
public function save() public function save()
{ {
@ -74,6 +74,7 @@ class d3user_totp extends AdminDetailsController
/** @var d3_totp_user $oUser */ /** @var d3_totp_user $oUser */
$oUser = oxNew(User::class); $oUser = oxNew(User::class);
$oUser->load($this->getEditObjectId()); $oUser->load($this->getEditObjectId());
if (false == $oUser->isSamePassword($pwd)) { if (false == $oUser->isSamePassword($pwd)) {
$oException = oxNew(StandardException::class, 'D3_TOTP_ERROR_PWDONTPASS'); $oException = oxNew(StandardException::class, 'D3_TOTP_ERROR_PWDONTPASS');
throw $oException; throw $oException;
@ -81,6 +82,7 @@ class d3user_totp extends AdminDetailsController
/** @var d3totp $oTotp */ /** @var d3totp $oTotp */
$oTotp = oxNew(d3totp::class); $oTotp = oxNew(d3totp::class);
$oTotpBackupCodes = oxNew(d3backupcodelist::class);
if ($aParams['d3totp__oxid']) { if ($aParams['d3totp__oxid']) {
$oTotp->load($aParams['d3totp__oxid']); $oTotp->load($aParams['d3totp__oxid']);
} else { } else {
@ -91,11 +93,12 @@ class d3user_totp extends AdminDetailsController
$oTotp->saveSecret($seed); $oTotp->saveSecret($seed);
$oTotp->assign($aParams); $oTotp->assign($aParams);
$oTotp->verify($otp, $seed); $oTotp->verify($otp, $seed);
$this->addTplParam('aBackupCodes', $oTotp->generateBackupCodes()); $oTotpBackupCodes->generateBackupCodes($this->getEditObjectId());
$oTotp->setId(); $oTotp->setId();
} }
$oTotp->save(); $oTotp->save();
} catch (\Exception $oExcp) { $oTotpBackupCodes->save();
} catch (Exception $oExcp) {
$this->_sSaveError = $oExcp->getMessage(); $this->_sSaveError = $oExcp->getMessage();
} }
} }
@ -111,4 +114,20 @@ class d3user_totp extends AdminDetailsController
$oTotp->delete(); $oTotp->delete();
} }
} }
/**
* @param $aCodes
*/
public function setBackupCodes($aCodes)
{
$this->aBackupCodes = $aCodes;
}
/**
* @return string
*/
public function getBackupCodes()
{
return implode(PHP_EOL, $this->aBackupCodes);
}
} }

Voir le fichier

@ -0,0 +1,118 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\Totp\Application\Model\Exceptions;
use D3\Totp\Application\Controller\Admin\d3user_totp;
use D3\Totp\Application\Model\d3backupcode;
use Exception;
use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Model\ListModel;
use OxidEsales\Eshop\Core\Registry;
class d3backupcodelist extends ListModel
{
protected $_sObjectsInListName = d3backupcode::class;
/**
* Core table name
*
* @var string
*/
protected $_sCoreTable = 'd3totp_backupcodes';
protected $_backupCodes = array();
/**
* @param $sUserId
* @throws DatabaseConnectionException
*/
public function generateBackupCodes($sUserId)
{
$this->deleteAllFromUser($sUserId);
for ($i = 1; $i <= 10; $i++) {
$oBackupCode = oxNew(d3backupcode::class);
$this->_backupCodes[] = $oBackupCode->generateCode($sUserId);
$this->offsetSet(md5(rand()), $oBackupCode);
}
/** @var d3user_totp $oActView */
$oActView = Registry::getConfig()->getActiveView();
$oActView->setBackupCodes($this->_backupCodes);
}
/**
* @throws Exception
*/
public function save()
{
/** @var d3backupcode $oBackupCode */
foreach ($this->getArray() as $oBackupCode) {
$oBackupCode->save();
}
}
/**
* @return d3backupcode
*/
public function getBaseObject()
{
/** @var d3backupcode $object */
$object = parent::getBaseObject();
return $object;
}
/**
* @param $totp
* @return bool
* @throws DatabaseConnectionException
*/
public function verify($totp)
{
$oDb = DatabaseProvider::getDb();
$query = "SELECT oxid FROM ".$this->getBaseObject()->getViewName().
" WHERE ".$oDb->quoteIdentifier('backupcode')." = ".$oDb->quote($this->getBaseObject()->d3EncodeBC($totp))." AND ".
$oDb->quoteIdentifier("oxuserid") ." = ".$oDb->quote($this->getUser()->getId());
$sVerify = $oDb->getOne($query);
$this->getBaseObject()->delete($sVerify);
return (bool) $sVerify;
}
/**
* @param $sUserId
* @throws DatabaseConnectionException
*/
public function deleteAllFromUser($sUserId)
{
$oDb = DatabaseProvider::getDb();
$query = "SELECT OXID FROM ".$oDb->quoteIdentifier($this->getBaseObject()->getCoreTableName()).
" WHERE ".$oDb->quoteIdentifier('oxuserid')." = ".$oDb->quote($sUserId);
$this->selectString($query);
/** @var d3backupcode $oBackupCode */
foreach ($this->getArray() as $oBackupCode) {
$oBackupCode->delete();
}
}
}

Voir le fichier

@ -17,6 +17,7 @@
namespace D3\Totp\Application\Model\Exceptions; namespace D3\Totp\Application\Model\Exceptions;
use Exception;
use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Exception\StandardException;
class d3totp_wrongOtpException extends StandardException class d3totp_wrongOtpException extends StandardException
@ -26,9 +27,9 @@ class d3totp_wrongOtpException extends StandardException
* *
* @param string $sMessage exception message * @param string $sMessage exception message
* @param integer $iCode exception code * @param integer $iCode exception code
* @param \Exception|null $previous previous exception * @param Exception|null $previous previous exception
*/ */
public function __construct($sMessage = "D3_TOTP_ERROR_UNVALID", $iCode = 0, \Exception $previous = null) public function __construct($sMessage = "D3_TOTP_ERROR_UNVALID", $iCode = 0, Exception $previous = null)
{ {
parent::__construct($sMessage, $iCode, $previous); parent::__construct($sMessage, $iCode, $previous);
} }

Voir le fichier

@ -0,0 +1,62 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\Totp\Application\Model;
use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Model\BaseModel;
use RandomLib\Factory;
use RandomLib\Generator;
class d3backupcode extends BaseModel
{
protected $_sCoreTable = 'd3totp_backupcodes';
/**
* @param $sUserId
* @return string
* @throws DatabaseConnectionException
*/
public function generateCode($sUserId)
{
$factory = new Factory();
$generator = $factory->getLowStrengthGenerator();
$sCode = $generator->generateString(6, Generator::CHAR_DIGITS);
$this->assign(
array(
'oxuserid' => $sUserId,
'backupcode' => $this->d3EncodeBC($sCode),
)
);
return $sCode;
}
/**
* @param $code
* @return false|string
* @throws DatabaseConnectionException
*/
public function d3EncodeBC($code)
{
$oDb = DatabaseProvider::getDb();
$salt = $this->getUser()->getFieldData('oxpasssalt');
$sSelect = "SELECT BINARY MD5( CONCAT( " . $oDb->quote($code) . ", UNHEX( ".$oDb->quote($salt)." ) ) )";
return $oDb->getOne($sSelect);
}
}

Voir le fichier

@ -18,6 +18,7 @@ namespace D3\Totp\Application\Model;
use BaconQrCode\Renderer\Image\Svg; use BaconQrCode\Renderer\Image\Svg;
use BaconQrCode\Writer; use BaconQrCode\Writer;
use D3\ModCfg\Application\Model\d3database; use D3\ModCfg\Application\Model\d3database;
use D3\Totp\Application\Model\Exceptions\d3backupcodelist;
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException; use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use OTPHP\TOTP; use OTPHP\TOTP;
@ -26,8 +27,6 @@ use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Model\BaseModel; use OxidEsales\Eshop\Core\Model\BaseModel;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use RandomLib\Factory;
use RandomLib\Generator;
class d3totp extends BaseModel class d3totp extends BaseModel
{ {
@ -37,7 +36,6 @@ class d3totp extends BaseModel
public $userId; public $userId;
public $totp; public $totp;
protected $timeWindow = 2; protected $timeWindow = 2;
protected $_backupCodes = array();
/** /**
* d3totp constructor. * d3totp constructor.
@ -119,28 +117,6 @@ class d3totp extends BaseModel
return null; return null;
} }
/**
* @return array
* @throws DatabaseConnectionException
*/
public function generateBackupCodes()
{
$factory = new Factory();
$generator = $factory->getLowStrengthGenerator();
for ($i = 1; $i <= 10; $i++) {
$sCode = $generator->generateString(6, Generator::CHAR_DIGITS);
$this->_backupCodes[] = $sCode;
$this->assign(
array(
'bc'.$i => $this->d3EncodeBC($sCode)
)
);
}
return $this->_backupCodes;
}
/** /**
* @param $seed * @param $seed
* @return TOTP * @return TOTP
@ -206,20 +182,6 @@ class d3totp extends BaseModel
); );
} }
/**
* @param $code
* @return false|string
* @throws DatabaseConnectionException
*/
public function d3EncodeBC($code)
{
$oDb = DatabaseProvider::getDb();
$salt = $this->getUser()->getFieldData('oxpasssalt');
$sSelect = "SELECT BINARY MD5( CONCAT( " . $oDb->quote($code) . ", UNHEX( ".$oDb->quote($salt)." ) ) )";
return $oDb->getOne($sSelect);
}
/** /**
* @param $totp * @param $totp
* @param $seed * @param $seed
@ -231,14 +193,9 @@ class d3totp extends BaseModel
{ {
$blVerify = $this->getTotp($seed)->verify($totp, null, $this->timeWindow); $blVerify = $this->getTotp($seed)->verify($totp, null, $this->timeWindow);
if (false == $blVerify) { if (false == $blVerify) {
$oDb = DatabaseProvider::getDb(); /** @var d3backupcodelist $oBC */
$aFields = array('bc1', 'bc2', 'bc3', 'bc4', 'bc5', 'bc6', 'bc7', 'bc8', 'bc9', 'bc10'); $oBC = oxNew(d3backupcodelist::class);
$blVerify = $oBC->verify($totp);
$query = "SELECT 1 FROM ".$this->getViewName().
" WHERE ".$oDb->quote($this->d3EncodeBC($totp))." IN (".implode(', ', array_map([$oDb, 'quoteIdentifier'], $aFields)).") AND ".
$oDb->quoteIdentifier("oxuserid") ." = ".$oDb->quote($this->getUser()->getId());
$blVerify = (bool) $oDb->getOne($query);
if (false == $blVerify) { if (false == $blVerify) {
$oException = oxNew(d3totp_wrongOtpException::class); $oException = oxNew(d3totp_wrongOtpException::class);
@ -283,4 +240,19 @@ class d3totp extends BaseModel
return false; return false;
} }
/**
* @param null $oxid
* @return bool
* @throws DatabaseConnectionException
*/
public function delete($oxid = null)
{
$oBackupCodeList = oxNew(d3backupcodelist::class);
$oBackupCodeList->deleteAllFromUser($this->getFieldData('oxuserid'));
$blDelete = parent::delete();
return $blDelete;
}
} }

Voir le fichier

@ -41,7 +41,7 @@ $aLang = [
'D3_TOTP_REGISTERDELETE_DESC' => 'Um die Registrierung zu ändern, löschen Sie diese bitte vorerst. Sie können sofort im Anschluss eine neue Registrierung anlegen.<br>Wenn Sie die Registrierung löschen, ist das Konto nicht mehr durch die Zweifaktorauthentisierung geschützt.', 'D3_TOTP_REGISTERDELETE_DESC' => 'Um die Registrierung zu ändern, löschen Sie diese bitte vorerst. Sie können sofort im Anschluss eine neue Registrierung anlegen.<br>Wenn Sie die Registrierung löschen, ist das Konto nicht mehr durch die Zweifaktorauthentisierung geschützt.',
'D3_TOTP_BACKUPCODES' => 'Backup-Codes', 'D3_TOTP_BACKUPCODES' => 'Backup-Codes',
'D3_TOTP_BACKUPCODES_DESC' => 'Mit diesen Backup-Codes können Sie sich anmelden, wenn die Generierung des Einmalpasswortes nicht möglich ist (z.B. Gerät verloren oder neu installiert). Sie können dann die Einstellungen zur Verwendung der 2-Faktor-Autetizierung aändern oder einen neuen Zugang erstellen. Speichern Sie sich diese Codes bitte in diesem Moment sicher ab. Nach Verlassen dieser Seite können diese Codes nicht erneut angezeigt werden.', 'D3_TOTP_BACKUPCODES_DESC' => 'Mit diesen Backup-Codes können Sie sich anmelden, wenn die Generierung des Einmalpasswortes nicht möglich ist (z.B. Gerät verloren oder neu installiert). Sie können dann die Einstellungen zur Verwendung der 2-Faktor-Authentisierung ändern oder einen neuen Zugang erstellen. Speichern Sie sich diese Codes bitte in diesem Moment sicher ab. Nach Verlassen dieser Seite können diese Codes nicht erneut angezeigt werden.',
'D3_TOTP_SAVE' => 'Speichern', 'D3_TOTP_SAVE' => 'Speichern',

Voir le fichier

@ -29,7 +29,7 @@
<input type="hidden" name="editval[d3totp__oxuserid]" value="[{$oxid}]"> <input type="hidden" name="editval[d3totp__oxuserid]" value="[{$oxid}]">
[{if $sSaveError}] [{if $sSaveError}]
<table cellspacing="0" cellpadding="0" border="0" style="width:98%;"> <table style="padding:0; border:0; width:98%;">
<tr> <tr>
<td></td> <td></td>
<td class="errorbox">[{oxmultilang ident=$sSaveError}]</td> <td class="errorbox">[{oxmultilang ident=$sSaveError}]</td>
@ -38,10 +38,10 @@
[{/if}] [{/if}]
[{if $oxid && $oxid != '-1'}] [{if $oxid && $oxid != '-1'}]
<table cellspacing="0" cellpadding="0" border="0" style="width:98%;"> <table style="padding:0; border:0; width:98%;">
<tr> <tr>
<td valign="top" class="edittext" style="padding-top:10px;padding-left:10px; width: 50%;"> <td class="edittext" style="vertical-align: top; padding-top:10px;padding-left:10px; width: 50%;">
<table cellspacing="0" cellpadding="0" border="0"> <table style="padding:0; border:0">
[{block name="user_d3user_totp_form1"}] [{block name="user_d3user_totp_form1"}]
[{if false == $totp->getId()}] [{if false == $totp->getId()}]
<tr> <tr>
@ -80,8 +80,8 @@
</table> </table>
</td> </td>
<!-- Anfang rechte Seite --> <!-- Anfang rechte Seite -->
<td valign="top" class="edittext" align="left" style="height:99%;padding-left:5px;padding-bottom:30px;padding-top:10px; width: 50%;"> <td class="edittext" style="text-align: left; vertical-align: top; height:99%;padding-left:5px;padding-bottom:30px;padding-top:10px; width: 50%;">
<table cellspacing="0" cellpadding="0" border="0"> <table style="padding:0; border:0">
[{block name="user_d3user_totp_form2"}] [{block name="user_d3user_totp_form2"}]
[{if false == $totp->getId()}] [{if false == $totp->getId()}]
<tr> <tr>
@ -124,7 +124,7 @@
</td> </td>
</tr> </tr>
[{else}] [{else}]
[{if $aBackupCodes}] [{if $oView->getBackupCodes()}]
<tr> <tr>
<td class="edittext" colspan="2"> <td class="edittext" colspan="2">
@ -136,10 +136,7 @@
<label for="backupcodes">[{oxmultilang ident="D3_TOTP_BACKUPCODES_DESC"}]</label> <label for="backupcodes">[{oxmultilang ident="D3_TOTP_BACKUPCODES_DESC"}]</label>
<br> <br>
<br> <br>
<textarea id="backupcodes" rows="10" cols="20">[{strip}] <textarea id="backupcodes" rows="10" cols="20">[{$oView->getBackupCodes()}]</textarea>
[{'
'|implode:$aBackupCodes}]
[{/strip}]</textarea>
</td> </td>
</tr> </tr>
[{/if}] [{/if}]

Voir le fichier

@ -27,6 +27,8 @@ class Installation extends d3install_updatebase
protected $_aUpdateMethods = array( protected $_aUpdateMethods = array(
array('check' => 'doesTotpTableNotExist', array('check' => 'doesTotpTableNotExist',
'do' => 'addTotpTable'), 'do' => 'addTotpTable'),
array('check' => 'doesTotpBCTableNotExist',
'do' => 'addTotpBCTable'),
array('check' => 'checkFields', array('check' => 'checkFields',
'do' => 'fixFields'), 'do' => 'fixFields'),
array('check' => 'checkIndizes', array('check' => 'checkIndizes',
@ -76,103 +78,54 @@ class Installation extends d3install_updatebase
'sExtra' => '', 'sExtra' => '',
'blMultilang' => false, 'blMultilang' => false,
), ),
'BC1' => array( 'OXTIMESTAMP' => array(
'sTableName' => 'd3totp', 'sTableName' => 'd3totp',
'sFieldName' => 'BC1', 'sFieldName' => 'OXTIMESTAMP',
'sType' => 'VARCHAR(64)', 'sType' => 'TIMESTAMP',
'blNull' => false, 'blNull' => false,
'sDefault' => false, 'sDefault' => 'CURRENT_TIMESTAMP',
'sComment' => 'BackupCode #1', 'sComment' => 'Timestamp',
'sExtra' => '', 'sExtra' => '',
'blMultilang' => false, 'blMultilang' => false,
), ),
'BC2' => array(
'sTableName' => 'd3totp', 'bc_OXID' => array(
'sFieldName' => 'BC2', 'sTableName' => 'd3totp_backupcodes',
'sType' => 'VARCHAR(64)', 'sFieldName' => 'OXID',
'sType' => 'CHAR(32)',
'blNull' => false, 'blNull' => false,
'sDefault' => false, 'sDefault' => false,
'sComment' => 'BackupCode #2', 'sComment' => '',
'sExtra' => '', 'sExtra' => '',
'blMultilang' => false, 'blMultilang' => false,
), ),
'BC3' => array( 'bc_OXUSERID' => array(
'sTableName' => 'd3totp', 'sTableName' => 'd3totp_backupcodes',
'sFieldName' => 'BC3', 'sFieldName' => 'OXUSERID',
'sType' => 'VARCHAR(64)', 'sType' => 'CHAR(32)',
'blNull' => false, 'blNull' => false,
'sDefault' => false, 'sDefault' => false,
'sComment' => 'BackupCode #3', 'sComment' => 'user id',
'sExtra' => '', 'sExtra' => '',
'blMultilang' => false, 'blMultilang' => false,
), ),
'BC4' => array( 'bc_BACKUPCODE' => array(
'sTableName' => 'd3totp', 'sTableName' => 'd3totp_backupcodes',
'sFieldName' => 'BC4', 'sFieldName' => 'BACKUPCODE',
'sType' => 'VARCHAR(64)', 'sType' => 'VARCHAR(64)',
'blNull' => false, 'blNull' => false,
'sDefault' => false, 'sDefault' => false,
'sComment' => 'BackupCode #4', 'sComment' => 'BackupCode',
'sExtra' => '', 'sExtra' => '',
'blMultilang' => false, 'blMultilang' => false,
), ),
'BC5' => array( 'bc_OXTIMESTAMP' => array(
'sTableName' => 'd3totp', 'sTableName' => 'd3totp_backupcodes',
'sFieldName' => 'BC5', 'sFieldName' => 'OXTIMESTAMP',
'sType' => 'VARCHAR(64)', 'sType' => 'TIMESTAMP',
'blNull' => false, 'blNull' => false,
'sDefault' => false, 'sDefault' => 'CURRENT_TIMESTAMP',
'sComment' => 'BackupCode #5', 'sComment' => 'Timestamp',
'sExtra' => '',
'blMultilang' => false,
),
'BC6' => array(
'sTableName' => 'd3totp',
'sFieldName' => 'BC6',
'sType' => 'VARCHAR(64)',
'blNull' => false,
'sDefault' => false,
'sComment' => 'BackupCode #6',
'sExtra' => '',
'blMultilang' => false,
),
'BC7' => array(
'sTableName' => 'd3totp',
'sFieldName' => 'BC7',
'sType' => 'VARCHAR(64)',
'blNull' => false,
'sDefault' => false,
'sComment' => 'BackupCode #7',
'sExtra' => '',
'blMultilang' => false,
),
'BC8' => array(
'sTableName' => 'd3totp',
'sFieldName' => 'BC8',
'sType' => 'VARCHAR(64)',
'blNull' => false,
'sDefault' => false,
'sComment' => 'BackupCode #8',
'sExtra' => '',
'blMultilang' => false,
),
'BC9' => array(
'sTableName' => 'd3totp',
'sFieldName' => 'BC9',
'sType' => 'VARCHAR(64)',
'blNull' => false,
'sDefault' => false,
'sComment' => 'BackupCode #9',
'sExtra' => '',
'blMultilang' => false,
),
'BC10' => array(
'sTableName' => 'd3totp',
'sFieldName' => 'BC10',
'sType' => 'VARCHAR(64)',
'blNull' => false,
'sDefault' => false,
'sComment' => 'BackupCode #10',
'sExtra' => '', 'sExtra' => '',
'blMultilang' => false, 'blMultilang' => false,
) )
@ -194,7 +147,31 @@ class Installation extends d3install_updatebase
'aFields' => array( 'aFields' => array(
'OXUSERID' => 'OXUSERID', 'OXUSERID' => 'OXUSERID',
), ),
) ),
'bc_OXID' => array(
'sTableName' => 'd3totp_backupcodes',
'sType' => d3database::INDEX_TYPE_PRIMARY,
'sName' => 'PRIMARY',
'aFields' => array(
'OXID' => 'OXID',
),
),
'bc_OXUSERID' => array(
'sTableName' => 'd3totp_backupcodes',
'sType' => d3database::INDEX_TYPE_INDEX,
'sName' => 'OXUSERID',
'aFields' => array(
'OXUSERID' => 'OXUSERID',
),
),
'bc_BACKUPCODE' => array(
'sTableName' => 'd3totp_backupcodes',
'sType' => d3database::INDEX_TYPE_INDEX,
'sName' => 'BACKUPCODE',
'aFields' => array(
'BACKUPCODE' => 'BACKUPCODE',
),
),
); );
protected $_aRefreshMetaModuleIds = array('d3totp'); protected $_aRefreshMetaModuleIds = array('d3totp');
@ -233,4 +210,39 @@ class Installation extends d3install_updatebase
return $blRet; return $blRet;
} }
/**
* @return bool
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function doesTotpBCTableNotExist()
{
return $this->_checkTableNotExist('d3totp_backupcodes');
}
/**
* @return bool
* @throws ConnectionException
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function addTotpBCTable()
{
$blRet = false;
if ($this->doesTotpBCTableNotExist()) {
$this->setInitialExecMethod(__METHOD__);
$blRet = $this->_addTable2(
'd3totp_backupcodes',
$this->aFields,
$this->aIndizes,
'totp backup codes',
'InnoDB'
);
}
return $blRet;
}
} }