src/Palladium/Mapper/StandardIdentity.php
<?php
namespace Palladium\Mapper;
/**
* SQL logic for authentication attempts using username/password
*/
use Palladium\Component\DataMapper;
use Palladium\Entity as Entity;
use PDOStatement;
use PDO;
class StandardIdentity extends DataMapper
{
/**
* @param Entity\StandardIdentity $entity
*/
public function exists(Entity\StandardIdentity $entity): bool
{
$sql = "SELECT 1
FROM {$this->table}
WHERE type = :type
AND fingerprint = :fingerprint
AND identifier = :identifier
AND (expires_on IS NULL OR expires_on > :now)";
$statement = $this->connection->prepare($sql);
$statement->bindValue(':type', Entity\StandardIdentity::TYPE_STANDARD);
$statement->bindValue(':fingerprint', $entity->getFingerprint());
$statement->bindValue(':identifier', $entity->getIdentifier());
$statement->bindValue(':now', time());
$statement->execute();
$data = $statement->fetch(PDO::FETCH_ASSOC);
return empty($data) === false;
}
/**
* @param Entity\StandardIdentity $entity
*/
public function fetch(Entity\StandardIdentity $entity)
{
if ($entity->getId()) {
$this->fetchById($entity);
return;
}
$this->fetchByIdentifier($entity);
}
private function fetchByIdentifier(Entity\StandardIdentity $entity)
{
$sql = "SELECT identity_id AS id,
account_id AS accountId,
hash AS hash,
status AS status,
used_on AS lastUsed,
token AS token,
token_action AS tokenAction,
token_expires_on AS tokenEndOfLife,
token_payload AS tokenPayload
FROM {$this->table}
WHERE type = :type
AND fingerprint = :fingerprint
AND identifier = :identifier";
$statement = $this->connection->prepare($sql);
$statement->bindValue(':type', $entity->getType());
$statement->bindValue(':identifier', $entity->getIdentifier());
$statement->bindValue(':fingerprint', $entity->getFingerprint());
$statement->execute();
$data = $statement->fetch(PDO::FETCH_ASSOC);
if ($data) {
if ($data['tokenPayload'] !== null) {
$data['tokenPayload'] = json_decode($data['tokenPayload'], true);
}
$this->applyValues($entity, $data);
}
}
private function fetchById(Entity\StandardIdentity $entity)
{
$sql = "SELECT identity_id AS id,
identifier AS identifier,
account_id AS accountId,
hash AS hash,
status AS status,
used_on AS lastUsed,
token AS token,
token_action AS tokenAction,
token_expires_on AS tokenEndOfLife,
token_payload AS tokenPayload
FROM {$this->table}
WHERE type = :type
AND identity_id = :id";
$statement = $this->connection->prepare($sql);
$statement->bindValue(':type', $entity->getType());
$statement->bindValue(':id', $entity->getId());
$statement->execute();
$data = $statement->fetch(PDO::FETCH_ASSOC);
if ($data) {
if ($data['tokenPayload'] !== null) {
$data['tokenPayload'] = json_decode($data['tokenPayload'], true);
}
$this->applyValues($entity, $data);
}
}
/**
* @param Entity\StandardIdentity $entity
*/
public function store(Entity\StandardIdentity $entity)
{
if ($entity->getId() === null) {
$this->createIdentity($entity);
return;
}
$this->updateIdentity($entity);
}
private function createIdentity(Entity\StandardIdentity $entity)
{
$sql = "INSERT INTO {$this->table}
(type, status, identifier, fingerprint, hash, created_on, token, token_action, token_expires_on, token_payload)
VALUES (:type, :status, :identifier, :fingerprint, :hash, :created, :token, :action, :token_eol, :payload)";
$statement = $this->connection->prepare($sql);
$statement->bindValue(':type', Entity\StandardIdentity::TYPE_STANDARD);
$statement->bindValue(':status', Entity\StandardIdentity::STATUS_NEW);
$statement->bindValue(':identifier', $entity->getIdentifier());
$statement->bindValue(':fingerprint', $entity->getFingerprint());
$statement->bindValue(':hash', $entity->getHash());
$statement->bindValue(':created', time());
$this->bindToken($statement, $entity);
$statement->execute();
$entity->setId($this->connection->lastInsertId());
}
private function updateIdentity(Entity\StandardIdentity $entity)
{
$sql = "UPDATE {$this->table}
SET hash = :hash,
identifier = :identifier,
fingerprint = :fingerprint,
status = :status,
used_on = :used,
expires_on = :expires,
token = :token,
token_action = :action,
token_expires_on = :token_eol,
token_payload = :payload
WHERE identity_id = :id";
$statement = $this->connection->prepare($sql);
$statement->bindValue(':id', $entity->getId());
$statement->bindValue(':hash', $entity->getHash());
$statement->bindValue(':identifier', $entity->getIdentifier());
$statement->bindValue(':fingerprint', $entity->getFingerprint());
$statement->bindValue(':status', $entity->getStatus());
$statement->bindValue(':used', $entity->getLastUsed());
$statement->bindValue(':expires', $entity->getExpiresOn());
$this->bindToken($statement, $entity);
$statement->execute();
}
private function bindToken(PDOStatement $statement, Entity\StandardIdentity $entity)
{
$statement->bindValue(':token', $entity->getToken());
$statement->bindValue(':action', $entity->getTokenAction());
$statement->bindValue(':token_eol', $entity->getTokenEndOfLife());
$payload = $entity->getTokenPayload();
if ($payload !== null) {
$payload = json_encode($payload);
}
$statement->bindValue(':payload', $payload);
}
}