Skip to content

Commit

Permalink
feat(kobo): Store the model and device_id
Browse files Browse the repository at this point in the history
  • Loading branch information
ragusa87 committed Nov 21, 2024
1 parent 29f39cb commit 5dfab43
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 5 deletions.
29 changes: 29 additions & 0 deletions migrations/Version20241121135658.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20241121135658 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add device_id to kobo device';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE kobo_device ADD device_id VARCHAR(255) DEFAULT NULL');
$this->addSql('CREATE INDEX kobo_device_id ON kobo_device (device_id);');
}

public function down(Schema $schema): void
{
$this->addSql('DROP INDEX kobo_device_id ON kobo_device;');
$this->addSql('ALTER TABLE kobo_device DROP device_id;');
}
}
31 changes: 31 additions & 0 deletions migrations/Version20241121142239.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241121142239 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add model to kobo device';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE kobo_device ADD model VARCHAR(255) DEFAULT NULL');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE kobo_device DROP model');
}
}
21 changes: 18 additions & 3 deletions src/Controller/Kobo/KoboAnalyticsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace App\Controller\Kobo;

use App\Entity\KoboDevice;
use App\Kobo\Proxy\KoboProxyConfiguration;
use App\Kobo\Proxy\KoboStoreProxy;
use App\Repository\KoboDeviceRepository;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
Expand All @@ -16,8 +18,12 @@
#[Route('/kobo/{accessKey}', name: 'kobo')]
class KoboAnalyticsController extends AbstractController
{
public function __construct(protected KoboProxyConfiguration $koboProxyConfiguration, protected KoboStoreProxy $koboStoreProxy, protected LoggerInterface $logger)
{
public function __construct(
protected KoboProxyConfiguration $koboProxyConfiguration,
protected KoboStoreProxy $koboStoreProxy,
protected KoboDeviceRepository $koboDeviceRepository,
protected LoggerInterface $logger
) {
}

/**
Expand Down Expand Up @@ -46,8 +52,17 @@ public function analyticsTests(Request $request): Response
* @throws GuzzleException
*/
#[Route('/v1/analytics/event', methods: ['POST'])]
public function analyticsEvent(Request $request): Response
public function analyticsEvent(Request $request, KoboDevice $kobo): Response
{
// Save the device_id and model
if ($request->headers->has(KoboDevice::KOBO_DEVICE_ID_HEADER)) {
$kobo->setDeviceId($request->headers->get(KoboDevice::KOBO_DEVICE_ID_HEADER));
if ($request->headers->has(KoboDevice::KOBO_DEVICE_MODEL)) {
$kobo->setModel($request->headers->get(KoboDevice::KOBO_DEVICE_MODEL));
}
$this->koboDeviceRepository->save($kobo);
}

$content = $request->getContent();
$json = trim($content) === '' ? [] : (array) json_decode($content, true, 512, JSON_THROW_ON_ERROR);
$this->logger->debug('Analytics event received', ['body' => $json]);
Expand Down
33 changes: 33 additions & 0 deletions src/Entity/KoboDevice.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@

#[ORM\Entity(repositoryClass: KoboDeviceRepository::class)]
#[ORM\UniqueConstraint(name: 'kobo_access_key', columns: ['access_key'])]
#[ORM\Index(columns: ['device_id'], name: 'kobo_device_id')]
#[ORM\Index(columns: ['access_key'], name: 'kobo_access_key')]
#[UniqueEntity(fields: ['accessKey'])]
class KoboDevice
{
use RandomGeneratorTrait;
public const KOBO_DEVICE_ID_HEADER = 'X-Kobo-Deviceid';
public const KOBO_DEVICE_MODEL = 'X-Kobo-Devicemodel';
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
Expand All @@ -34,6 +38,11 @@ class KoboDevice
#[Assert\Regex(pattern: '/^[a-f0-9]+$/', message: 'Need to be Hexadecimal')]
private ?string $accessKey = null;

#[ORM\Column(length: 255, nullable: true)]
private ?string $deviceId = null;

#[ORM\Column(length: 255, nullable: true)]
private ?string $model = null;
/**
* @var Collection<int, Shelf>
*/
Expand Down Expand Up @@ -162,4 +171,28 @@ public function removeShelf(Shelf $shelf): void
{
$this->shelves->removeElement($shelf);
}

public function getDeviceId(): ?string
{
return $this->deviceId;
}

public function setDeviceId(?string $deviceId): self
{
$this->deviceId = $deviceId;

return $this;
}

public function getModel(): ?string
{
return $this->model;
}

public function setModel(?string $model): self
{
$this->model = $model;

return $this;
}
}
10 changes: 10 additions & 0 deletions src/Form/KoboType.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
$builder
->add('name')
->add('accessKey')
->add('deviceId', null, [
'label' => 'Device ID',
'disabled' => true,
'required' => false,
])
->add('model', null, [
'label' => 'Model',
'disabled' => true,
'required' => false,
])
->add('forceSync', null, [
'label' => 'Force Sync',
'required' => false,
Expand Down
6 changes: 6 additions & 0 deletions src/Repository/KoboDeviceRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,10 @@ public function findAllByUser(?UserInterface $user = null): array

return $result;
}

public function save(KoboDevice $kobo): void
{
$this->_em->persist($kobo);
$this->_em->flush();
}
}
6 changes: 5 additions & 1 deletion templates/kobodevice_user/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
<tbody>
{% for kobo in kobos %}
<tr>
<td>{{ kobo.name }}</td>
<td>{{ kobo.name }}
{% if kobo.model is not empty %}
<br /><small class="text-muted">{{ kobo.model }}</small>
{% endif %}
</td>
<td>{{ kobo.accessKey }}</td>
<td>
{% if is_granted('EDIT', kobo) %}
Expand Down
15 changes: 14 additions & 1 deletion tests/Controller/Kobo/KoboAnalyticsControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
namespace App\Tests\Controller\Kobo;


use App\Entity\KoboDevice;

class KoboAnalyticsControllerTest extends AbstractKoboControllerTest
{
const SERIAL_NUMBER = 'N9413679432456';
const DEVICE_ID = '2a92bba197b1e0574a3f7d29cb2b05b399ab0d197e6b1aa230bfb75a920b14e7c';
const MODEL = 'Kobo Libra H2O';
const APP_VERSION = '4.38.21908';

public function testPostEvent(): void
Expand Down Expand Up @@ -442,9 +446,18 @@ public function testPostEvent(): void
];
$client = static::getClient();
$client?->setServerParameter('HTTP_CONNECTION', 'keep-alive');
$server = [
'HTTP_'.KoboDevice::KOBO_DEVICE_ID_HEADER => self::DEVICE_ID,
'HTTP_'.KoboDevice::KOBO_DEVICE_MODEL => self::MODEL,
];
$client?->request('POST', '/kobo/'.$this->accessKey.'/v1/analytics/event', [
'json' => $body,
]);
], [], $server);

// Make sure we define Kobo's device_id and model
$kobo = $this->getKoboDevice(true);
self::assertSame(self::DEVICE_ID,$kobo->getDeviceId());
self::assertSame(self::MODEL,$kobo->getModel());

self::assertResponseIsSuccessful();
self::assertResponseHeaderSame('Connection', 'keep-alive');
Expand Down

0 comments on commit 5dfab43

Please sign in to comment.