refactor to show existing registrations in admin

This commit is contained in:
Daniel Seifert 2022-10-25 01:01:10 +02:00
parent b5b3117fec
commit d7e429709e
Signed by: DanielS
GPG Key ID: 6A513E13AEE66170
13 changed files with 303 additions and 278 deletions

View File

@ -15,9 +15,8 @@
namespace D3\Webauthn\Application\Controller\Admin;
use D3\Webauthn\Application\Model\Credential\d3PublicKeyCredentialList;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList;
use D3\Webauthn\Application\Model\d3webauthn;
use D3\Webauthn\Application\Model\Webauthn\d3PublicKeyCredentialUserEntity;
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
use Exception;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
@ -59,7 +58,7 @@ class d3user_webauthn extends AdminDetailsController
$this->addTplParam("sSaveError", $this->_sSaveError);
}
$this->setAuthnRegister();
// $this->setAuthnRegister();
return $this->_sThisTemplate;
}
@ -79,23 +78,15 @@ class d3user_webauthn extends AdminDetailsController
/**
* @param $userId
* @return d3PublicKeyCredentialList|object
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @return array
*/
public function getCredentialList($userId)
{
$credentialList = oxNew(d3PublicKeyCredentialList::class);
$oUser = $this->getUserObject();
$oUser->load($userId);
if ($oUser && $oUser->getId()) {
/** @var d3PublicKeyCredentialUserEntity $userEntity */
$userEntity = oxNew(d3PublicKeyCredentialUserEntity::class, $oUser);
$credentialList->loadAllForUserEntity($userEntity);
}
return $credentialList;
$publicKeyCrendetials = oxNew(PublicKeyCredentialList::class);
return $publicKeyCrendetials->getAllFromUser($oUser)->getArray();
}
/**

View File

@ -15,8 +15,8 @@
namespace D3\Webauthn\Application\Controller;
use D3\Webauthn\Application\Model\Credential\d3PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\d3PublicKeyCredentialList;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList;
use D3\Webauthn\Application\Model\d3webauthn;
use D3\Webauthn\Application\Model\Webauthn\d3PublicKeyCredentialUserEntity;
use OxidEsales\Eshop\Application\Controller\AccountController;
@ -50,19 +50,19 @@ dumpvar(Registry::getRequest()->getRequestEscapedParameter('error'));
$this->addTplParam('user', $this->getUser());
$this->setAuthnRegister();
// $this->setAuthnRegister();
return $sRet;
}
/**
* @return d3PublicKeyCredentialList|object
* @return publicKeyCredentialList|object
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function getCredentialList()
{
$credentialList = oxNew(d3PublicKeyCredentialList::class);
$credentialList = oxNew(PublicKeyCredentialList::class);
$oUser = $this->getUser();
if ($oUser) {
@ -98,7 +98,7 @@ dumpvar(Registry::getRequest()->getRequestEscapedParameter('error'));
public function deleteKey()
{
if (Registry::getRequest()->getRequestEscapedParameter('oxid')) {
$credential = oxNew(d3PublicKeyCredential::class);
$credential = oxNew(publicKeyCredential::class);
$credential->delete(Registry::getRequest()->getRequestEscapedParameter('oxid'));
}
}

View File

@ -0,0 +1,140 @@
<?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\Webauthn\Application\Model\Credential;
use Doctrine\DBAL\Query\QueryBuilder;
use OxidEsales\Eshop\Core\Model\BaseModel;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use Webauthn\PublicKeyCredentialSource;
class PublicKeyCredential extends BaseModel
{
protected $_sCoreTable = 'd3wa_usercredentials';
public function __construct()
{
$this->init($this->getCoreTableName());
parent::__construct();
}
/*
public function setName($name)
{
$this->assign(['name' => $name]);
}
public function getName()
{
return $this->getFieldData('name');
}
*/
public function setCredentialId($credentialId)
{
$this->assign([
'credentialid' => bin2hex($credentialId)
]);
}
public function getCredentialId()
{
return hex2bin($this->__get($this->_getFieldLongName('credentialid'))->rawValue);
}
public function setUserId($userId)
{
$this->assign([
'oxuserid' => $userId
]);
}
public function getUserId()
{
return $this->__get($this->_getFieldLongName('oxuserid'))->rawValue;
}
public function setCredential($credential)
{
$this->assign([
'credential' => bin2hex(serialize($credential))
]);
}
public function getCredential()
{
return unserialize(hex2bin($this->__get($this->_getFieldLongName('credential'))->rawValue));
}
/*
public function setPublicKey($publicKey)
{
$this->assign(['PublicKey' => $publicKey]);
}
public function getPublicKey()
{
return $this->__get($this->_getFieldLongName('PublicKey'))->rawValue;
}
/**
* @param PublicKeyCredentialSource $publicKeyCredentialSource
* @return void
* @throws \Exception
*/
public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void
{
// will save on every successfully assertion, set id to prevent duplicated database entries
$id = $this->getIdByCredentialId($publicKeyCredentialSource->getPublicKeyCredentialId());
$this->setId($id);
$this->setShopId(Registry::getConfig()->getShopId());
$this->setUserId($publicKeyCredentialSource->getUserHandle());
$this->setCredentialId($publicKeyCredentialSource->getPublicKeyCredentialId());
$this->setCredential($publicKeyCredentialSource);
// ToDo: required??
$this->assign([
'pubkey_hex' => bin2hex($publicKeyCredentialSource->getCredentialPublicKey()),
]);
$this->save();
}
public function getIdByCredentialId(string $publicKeyCredentialId): ?string
{
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('oxid')
->from($this->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'credid_hex',
$qb->createNamedParameter(bin2hex($publicKeyCredentialId))
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
)
)
);
$oxid = $qb->execute()->fetchOne();
return strlen($oxid) ? $oxid : null;
}
}

View File

@ -0,0 +1,131 @@
<?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\Webauthn\Application\Model\Credential;
use Doctrine\DBAL\Query\QueryBuilder;
use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\Model\ListModel;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use phpDocumentor\Reflection\Types\This;
use Webauthn\PublicKeyCredentialSource;
use Webauthn\PublicKeyCredentialSourceRepository;
use Webauthn\PublicKeyCredentialUserEntity;
class PublicKeyCredentialList extends ListModel implements PublicKeyCredentialSourceRepository
{
protected $_sObjectsInListName = PublicKeyCredential::class;
public function __construct()
{
parent::__construct(PublicKeyCredential::class);
}
public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource
{
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('credential')
->from($this->getBaseObject()->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'credid_hex',
$qb->createNamedParameter(bin2hex($publicKeyCredentialId))
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
)
)
);
$credential = $qb->execute()->fetchOne();
if (!strlen($credential)) {
return null;
}
$credential = unserialize(hex2bin($credential));
return $credential instanceof PublicKeyCredentialSource ? $credential : null;
}
public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array
{
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('credential')
->from($this->getBaseObject()->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'oxuserid',
$qb->createNamedParameter($publicKeyCredentialUserEntity->getId())
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
)
)
);
// generate decoded credentials list
return array_map(function (array $fields) {
return unserialize(hex2bin($fields['credential']));
}, $qb->execute()->fetchAllAssociative());
}
public function getAllFromUser(User $user)
{
if (!$user->isLoaded()) {
return $this;
}
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('oxid')
->from($this->getBaseObject()->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'oxuserid',
$qb->createNamedParameter($user->getId())
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
)
)
);
foreach ($qb->execute()->fetchAllAssociative() as $fields) {
$id = $fields['oxid'];
$credential = clone $this->getBaseObject();
$credential->load($id);
$this->offsetSet($id, $credential);
}
return $this;
}
public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void
{
$this->getBaseObject()->saveCredentialSource($publicKeyCredentialSource);
}
}

View File

@ -1,29 +0,0 @@
<?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\Webauthn\Application\Model\Credential;
use Webauthn\MetadataService\MetadataStatement;
use Webauthn\MetadataService\MetadataStatementRepository;
class d3MetadataStatementRepository implements MetadataStatementRepository
{
public function findOneByAAGUID(string $aaguid): ?MetadataStatement
{
return new MetadataStatement();
}
}

View File

@ -1,153 +0,0 @@
<?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\Webauthn\Application\Model\Credential;
use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Model\BaseModel;
use OxidEsales\Eshop\Core\Registry;
class d3PublicKeyCredential extends BaseModel
{
protected $_sCoreTable = 'd3PublicKeyCredential';
public function __construct()
{
$this->init($this->getCoreTableName());
parent::__construct();
}
public function d3SetName($name)
{
$this->assign(['name' => $name]);
}
public function d3GetName()
{
return $this->getFieldData('name');
}
public function d3SetCredentialId($credentialId)
{
$this->assign(['credentialid' => $credentialId]);
}
public function d3GetCredentialId()
{
return $this->__get($this->_getFieldLongName('credentialid'))->rawValue;
}
public function d3SetType($type)
{
$this->assign(['Type' => $type]);
}
public function d3GetType()
{
return $this->getFieldData('Type');
}
public function d3SetTransports($transports)
{
$this->assign(['Transports' => base64_encode(serialize($transports))]);
}
public function d3GetTransports()
{
return unserialize(base64_decode($this->getFieldData('Transports')));
}
public function d3SetAttestationType($attestationType)
{
$this->assign(['AttestationType' => $attestationType]);
}
public function d3GetAttestationType()
{
return $this->getFieldData('AttestationType');
}
public function d3SetTrustPath($trustPath)
{
$this->assign(['TrustPath' => base64_encode(serialize($trustPath))]);
}
public function d3GetTrustPath()
{
return unserialize(base64_decode($this->getFieldData('TrustPath')));
}
public function d3SetAaguid($aaguid)
{
$this->assign(['Aaguid' => base64_encode(serialize($aaguid))]);
}
public function d3GetAaguid()
{
return unserialize(base64_decode($this->getFieldData('Aaguid')));
}
public function d3SetPublicKey($publicKey)
{
$this->assign(['PublicKey' => $publicKey]);
}
public function d3GetPublicKey()
{
return $this->__get($this->_getFieldLongName('PublicKey'))->rawValue;
}
public function d3SetUserHandle($userHandle)
{
$this->assign(['UserHandle' => $userHandle]);
}
public function d3GetUserHandle()
{
return $this->getFieldData('UserHandle');
}
public function d3SetCounter($count)
{
$this->assign(['Counter' => $count]);
}
public function d3GetCounter()
{
return $this->getFieldData('Counter');
}
/**
* @param string $publicKeyCredentialId
* @return |null
* @throws DatabaseConnectionException
*/
public function loadByCredentialId(string $publicKeyCredentialId)
{
if (Registry::getRequest()->getRequestEscapedParameter('fnc') == 'checkregister') {
return null;
}
$oDb = DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC);
$q = "SELECT oxid FROM ".$this->getViewName()." WHERE CredentialId = ".$oDb->quote($publicKeyCredentialId);
$id = $oDb->getOne($q);
$this->load($id);
}
}

View File

@ -1,53 +0,0 @@
<?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\Webauthn\Application\Model\Credential;
use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Model\ListModel;
use Webauthn\PublicKeyCredentialUserEntity;
class d3PublicKeyCredentialList extends ListModel
{
protected $_sObjectsInListName = d3PublicKeyCredential::class;
public function __construct()
{
parent::__construct(d3PublicKeyCredential::class);
}
/**
* @param PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function loadAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity)
{
$q = "SELECT oxid FROM ".$this->getBaseObject()->getViewName()." WHERE UserHandle = ".DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->quote($publicKeyCredentialUserEntity->getId());
$idList = DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->getAll($q);
if ($idList && is_iterable($idList)) {
foreach ($idList as $id) {
$credential = oxNew($this->_sObjectsInListName);
$credential->load($id['oxid']);
$this->offsetSet($credential->getId(), $credential);
}
}
}
}

View File

@ -17,7 +17,7 @@
namespace D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\Credential\d3PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\publicKeyCredential;
use Webauthn\PublicKeyCredentialSource;
class d3PublicKeyCredentialSource extends PublicKeyCredentialSource
@ -27,7 +27,7 @@ class d3PublicKeyCredentialSource extends PublicKeyCredentialSource
*/
public function saveCredential()
{
$credential = oxNew(d3PublicKeyCredential::class);
$credential = oxNew(publicKeyCredential::class);
$credential->d3SetName(date('Y-m-d H:i:s'));
$credential->d3SetCredentialId($this->getPublicKeyCredentialId());
$credential->d3SetType($this->getType());
@ -42,7 +42,7 @@ class d3PublicKeyCredentialSource extends PublicKeyCredentialSource
$credential->save();
}
public static function createFromd3PublicKeyCredential(d3PublicKeyCredential $publicKeyCredential): self
public static function createFromd3PublicKeyCredential(publicKeyCredential $publicKeyCredential): self
{
return new self(
$publicKeyCredential->d3GetCredentialId(),

View File

@ -19,8 +19,8 @@ declare(strict_types=1);
namespace D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\Credential\d3PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\d3PublicKeyCredentialList;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList;
use Exception;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
@ -42,7 +42,7 @@ class d3PublicKeyCredentialSourceRepository implements PublicKeyCredentialSource
return null;
}
$credential = oxNew(d3PublicKeyCredential::class);
$credential = oxNew(publicKeyCredential::class);
$credential->loadByCredentialId($publicKeyCredentialId);
return $credential->getId() ?
@ -60,10 +60,10 @@ class d3PublicKeyCredentialSourceRepository implements PublicKeyCredentialSource
{
$sourceList = [];
$credentialList = oxNew(d3PublicKeyCredentialList::class);
$credentialList = oxNew(PublicKeyCredentialList::class);
$credentialList->loadAllForUserEntity($publicKeyCredentialUserEntity);
/** @var d3PublicKeyCredential $credential */
/** @var publicKeyCredential $credential */
foreach ($credentialList->getArray() as $credential) {
$sourceList[$credential->getId()] = d3PublicKeyCredentialSource::createFromd3PublicKeyCredential($credential);
};

View File

@ -10,7 +10,7 @@
[{assign var="readonly" value=""}]
[{/if}]
<style type="text/css">
<style>
td.edittext {
white-space: normal;
}
@ -153,12 +153,15 @@ console.log('96');
</tr>
[{foreach from=$oView->getCredentialList($userid) item="credential"}]
<tr>
[{***
<td class="edittext">
<label for="secret">[{$credential->d3GetName()}]</label>
</td>
***}]
<td class="edittext">
<a href="#" onclick="toggle('keydetails_[{$credential->getId()}]'); return false;" class="list-group-item">
[{$credential->d3GetName()}] (last used: XX)
[{** [{$credential->d3GetName()}] (last used: XX) **}]
[{$credential->getId()}]
</a>
<div class="list-group-item" id="keydetails_[{$credential->getId()}]" style="display: none">
<a onclick="deleteItem('[{$credential->getId()}]'); return false;"><span class="glyphicon glyphicon-pencil">delete</span></a>

View File

@ -36,7 +36,7 @@ class d3_StartController_Webauthn extends d3_StartController_Webauthn_parent
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function render()
public function ___render()
{
if (!Registry::getRequest()->getRequestEscapedParameter('authn')) {
/*** register ***/
@ -49,12 +49,7 @@ class d3_StartController_Webauthn extends d3_StartController_Webauthn_parent
$publicKeyCredentialSourceRepository,
new d3MetadataStatementRepository()
);
/*
if (!($user = Registry::getSession()->getUser())) {
$e = oxNew(\Exception::class, 'no user loaded');
throw $e;
}
*/
$user = oxNew(User::class);
//$user->load('oxdefaultadmin');
$user->load('36944b76d6e583fe2.12734046');
@ -110,7 +105,7 @@ class d3_StartController_Webauthn extends d3_StartController_Webauthn_parent
return $return;
}
public function checkregister()
public function ____checkregister()
{
// Retrieve the PublicKeyCredentialCreationOptions object created earlier
/** @var PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions */
@ -157,7 +152,7 @@ class d3_StartController_Webauthn extends d3_StartController_Webauthn_parent
dumpvar('registered');
}
public function checklogin()
public function _____checklogin()
{
// Retrieve the Options passed to the device
$publicKeyCredentialRequestOptions = Registry::getSession()->getVariable('authnloginobject');

View File

@ -38,7 +38,7 @@ class Events
public static function onActivate()
{
if (class_exists(d3install::class)) {
d3install::checkUpdateStart();
//d3install::checkUpdateStart();
}
}

View File

@ -79,9 +79,9 @@ $aModule = array(
'd3_account_webauthn' => d3_account_webauthn::class
],
'templates' => [
'd3user_webauthn.tpl' => 'd3/webauthn/Application/views/admin/tpl/d3user_webauthn.tpl',
'd3webauthnlogin.tpl' => 'd3/webauthn/Application/views/tpl/d3webauthnlogin.tpl',
'd3_account_webauthn.tpl' => 'd3/webauthn/Application/views/tpl/d3_account_webauthn.tpl',
'd3user_webauthn.tpl' => 'd3/oxwebauthn/Application/views/admin/tpl/d3user_webauthn.tpl',
'd3webauthnlogin.tpl' => 'd3/oxwebauthn/Application/views/tpl/d3webauthnlogin.tpl',
'd3_account_webauthn.tpl' => 'd3/oxwebauthn/Application/views/tpl/d3_account_webauthn.tpl',
],
'events' => [
'onActivate' => '\D3\Webauthn\Setup\Events::onActivate',