Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds projects support #150

Merged
merged 21 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Adds projects support
issue #149
  • Loading branch information
butschster committed Apr 26, 2024
commit 181d86512ede4733c62e40bbe6f0b11f2de673dc
1 change: 1 addition & 0 deletions app/config/cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
'default' => env('CACHE_STORAGE', 'roadrunner'),
'aliases' => [
'events' => ['storage' => $defaultStorage, 'prefix' => 'events:'],
'projects' => ['storage' => $defaultStorage, 'prefix' => 'projects:'],
'webhooks' => ['storage' => $defaultStorage, 'prefix' => 'webhooks:'],
'local' => ['storage' => $defaultStorage, 'prefix' => 'local:'],
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Migration;

use Cycle\Migrations\Migration;

class OrmDefault5b1ee362e1b19b19f535c6f9da36cb55 extends Migration
{
protected const DATABASE = 'default';

public function up(): void
{
$this->table('events')
->addColumn('project', 'string', ['nullable' => true, 'defaultValue' => null, 'size' => 255])
->dropColumn('project_id')
->update();
}

public function down(): void
{
$this->table('events')
->addColumn('project_id', 'integer', ['nullable' => true, 'defaultValue' => null])
->dropColumn('project')
->update();
}
}
26 changes: 26 additions & 0 deletions app/migrations/20240426.171505_1_1_default_create_projects.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Migration;

use Cycle\Migrations\Migration;

class OrmDefault2a897d68b0647d8ad446d9074be5a172 extends Migration
{
protected const DATABASE = 'default';

public function up(): void
{
$this->table('projects')
->addColumn('key', 'string', ['nullable' => false, 'defaultValue' => null, 'size' => 36])
->addColumn('name', 'string', ['nullable' => false, 'defaultValue' => null, 'size' => 255])
->setPrimaryKeys(['key'])
->create();
}

public function down(): void
{
$this->table('projects')->drop();
}
}
9 changes: 4 additions & 5 deletions app/modules/Events/Domain/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use App\Application\Domain\ValueObjects\Uuid;
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use DateTimeImmutable;

#[Entity(
repository: EventRepositoryInterface::class
Expand All @@ -29,8 +28,8 @@ public function __construct(
#[Column(type: 'float')]
private float $timestamp,

#[Column(type: 'integer', nullable: true)]
private ?int $projectId,
#[Column(type: 'string', nullable: true)]
private ?string $project = null,
) {
}

Expand All @@ -54,8 +53,8 @@ public function getTimestamp(): float
return $this->timestamp;
}

public function getProjectId(): ?int
public function getProject(): ?string
{
return $this->projectId;
return $this->project;
}
}
4 changes: 2 additions & 2 deletions app/modules/Events/Domain/Events/EventWasReceived.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ public function __construct(
public string $type,
public array $payload,
public float $timestamp,
public ?int $projectId = null,
public ?string $project = null,
) {
}

public function jsonSerialize(): array
{
return [
'projectId' => $this->projectId,
'project' => $this->project,
'uuid' => (string)$this->uuid,
'type' => $this->type,
'payload' => $this->payload,
Expand Down
19 changes: 6 additions & 13 deletions app/modules/Events/Interfaces/Commands/StoreEventHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

namespace Modules\Events\Interfaces\Commands;

use App\Application\Commands\FindProjectByName;
use App\Application\Commands\HandleReceivedEvent;
use App\Application\Domain\Entity\Json;
use Carbon\Carbon;
use Modules\Events\Domain\Event;
use Modules\Events\Domain\EventRepositoryInterface;
use Modules\Events\Domain\Events\EventWasReceived;
Expand All @@ -27,18 +25,13 @@ public function __construct(
#[CommandHandler]
public function handle(HandleReceivedEvent $command): void
{
$projectId = null;
if ($command->project !== null) {
$projectId = $this->queryBus->ask(new FindProjectByName($command->project));
}

$this->events->store(
new Event(
$command->uuid,
$command->type,
new Json($command->payload),
$command->timestamp,
$projectId,
uuid: $command->uuid,
type: $command->type,
payload: new Json($command->payload),
timestamp: $command->timestamp,
project: $command->project,
),
);

Expand All @@ -48,7 +41,7 @@ public function handle(HandleReceivedEvent $command): void
type: $command->type,
payload: $command->payload,
timestamp: $command->timestamp,
projectId: $projectId,
project: $command->project,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
new OA\Property(property: 'type', type: 'string'),
new OA\Property(property: 'payload', description: 'Event payload based on type', type: 'object'),
new OA\Property(property: 'timestamp', type: 'float', example: 1630540800.12312),
new OA\Property(property: 'project', description: 'Project', type: 'string', format: 'uuid'),
],
)]
final class EventResource extends JsonResource
Expand All @@ -34,7 +35,7 @@ protected function mapData(): array|\JsonSerializable
'type' => $this->data->getType(),
'payload' => $this->data->getPayload(),
'timestamp' => $this->data->getTimestamp(),
'project_id' => $this->data->getProjectId(),
'project' => $this->data->getProject(),
];
}
}
4 changes: 2 additions & 2 deletions app/modules/Events/Interfaces/Queries/EventsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ protected static function getScopeFromFindEvents(AskEvents $query): array
if ($query->type !== null) {
$scope['type'] = $query->type;
}
if ($query->projectId !== null) {
$scope['project_id'] = $query->projectId;
if ($query->project !== null) {
$scope['project'] = $query->project;
}

return $scope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Modules\HttpDumps\Interfaces\Http\Handler;

use App\Application\Commands\HandleReceivedEvent;
use App\Application\Event\EventType;
use App\Application\Service\HttpHandler\HandlerInterface;
use Carbon\Carbon;
use Modules\HttpDumps\Application\EventHandlerInterface;
Expand All @@ -16,14 +17,14 @@
use Spiral\Storage\BucketInterface;
use Spiral\Storage\StorageInterface;

final class AnyHttpRequestDump implements HandlerInterface
final readonly class AnyHttpRequestDump implements HandlerInterface
{
private readonly BucketInterface $bucket;
private BucketInterface $bucket;

public function __construct(
private readonly CommandBusInterface $commands,
private readonly EventHandlerInterface $handler,
private readonly ResponseWrapper $responseWrapper,
private CommandBusInterface $commands,
private EventHandlerInterface $handler,
private ResponseWrapper $responseWrapper,
StorageInterface $storage,
) {
$this->bucket = $storage->bucket('attachments');
Expand All @@ -34,16 +35,11 @@ public function priority(): int
return 0;
}

private function isValidRequest(ServerRequestInterface $request): bool
{
return $request->getHeaderLine('X-Buggregator-Event') === 'http-dump'
|| $request->getAttribute('event-type') === 'http-dump'
|| $request->getUri()->getUserInfo() === 'http-dump';
}

public function handle(ServerRequestInterface $request, \Closure $next): ResponseInterface
{
if (!$this->isValidRequest($request)) {
$eventType = $this->listenEvent($request);

if ($eventType === null) {
return $next($request);
}

Expand All @@ -52,7 +48,7 @@ public function handle(ServerRequestInterface $request, \Closure $next): Respons
$event = $this->handler->handle($payload);

$this->commands->dispatch(
new HandleReceivedEvent(type: 'http-dump', payload: $event),
new HandleReceivedEvent(type: $eventType->type, payload: $event, project: $eventType->project),
);

return $this->responseWrapper->create(200);
Expand Down Expand Up @@ -94,4 +90,16 @@ function (UploadedFileInterface $attachment) use ($id) {
],
];
}

private function listenEvent(ServerRequestInterface $request): ?EventType
{
/** @var EventType|null $event */
$event = $request->getAttribute('event');

if ($event?->type === 'http-dump') {
return $event;
}

return null;
}
}
12 changes: 11 additions & 1 deletion app/modules/Inspector/Application/InspectorBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@
namespace Modules\Inspector\Application;

use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Boot\EnvironmentInterface;

final class InspectorBootloader extends Bootloader
{

public function defineSingletons(): array
{
return [
SecretKeyValidator::class => static fn(
EnvironmentInterface $env,
): SecretKeyValidator => new SecretKeyValidator(
secret: $env->get('INSPECTOR_SECRET_KEY'),
),
];
}
}
30 changes: 30 additions & 0 deletions app/modules/Inspector/Application/SecretKeyValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Modules\Inspector\Application;

use Psr\Http\Message\ServerRequestInterface;
use Spiral\Core\Attribute\Singleton;

#[Singleton]
final readonly class SecretKeyValidator
{
public function __construct(
private ?string $secret = null,
) {
}

public function validateRequest(ServerRequestInterface $request): bool
{
if ($this->secret === null) {
return true;
}

if (!$request->hasHeader('X-Inspector-Key')) {
return false;
}

return $this->secret === $request->getHeaderLine('X-Inspector-Key');
}
}
34 changes: 26 additions & 8 deletions app/modules/Inspector/Interfaces/Http/Handler/EventHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
namespace Modules\Inspector\Interfaces\Http\Handler;

use App\Application\Commands\HandleReceivedEvent;
use App\Application\Event\EventType;
use App\Application\Service\HttpHandler\HandlerInterface;
use Modules\Inspector\Application\SecretKeyValidator;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Spiral\Cqrs\CommandBusInterface;
Expand All @@ -17,6 +19,7 @@
public function __construct(
private ResponseWrapper $responseWrapper,
private CommandBusInterface $commands,
private SecretKeyValidator $secretKeyValidator,
) {
}

Expand All @@ -27,10 +30,15 @@ public function priority(): int

public function handle(ServerRequestInterface $request, \Closure $next): ResponseInterface
{
if (!$this->isValidRequest($request)) {
$eventType = $this->listenEvent($request);
if ($eventType === null) {
return $next($request);
}

if (!$this->secretKeyValidator->validateRequest($request)) {
throw new ClientException\ForbiddenException('Invalid secret key');
}

$data = \json_decode(\base64_decode((string)$request->getBody()), true)
?? throw new ClientException\BadRequestException('Invalid data');

Expand All @@ -45,19 +53,29 @@ public function handle(ServerRequestInterface $request, \Closure $next): Respons
};

$this->commands->dispatch(
new HandleReceivedEvent(type: 'inspector', payload: $data),
new HandleReceivedEvent(type: $eventType->type, payload: $data, project: $eventType->project),
);

return $this->responseWrapper->create(200);
}

private function isValidRequest(ServerRequestInterface $request): bool
private function listenEvent(ServerRequestInterface $request): ?EventType
{
return $request->getHeaderLine('X-Buggregator-Event') === 'inspector'
|| $request->getAttribute('event-type') === 'inspector'
|| $request->getUri()->getUserInfo() === 'inspector'
|| $request->hasHeader('X-Inspector-Key')
/** @var EventType|null $event */
$event = $request->getAttribute('event');

if ($event?->type === 'inspector') {
return $event;
}

if (
$request->hasHeader('X-Inspector-Key')
|| $request->hasHeader('X-Inspector-Version')
|| \str_ends_with((string)$request->getUri(), 'inspector');
|| \str_ends_with((string)$request->getUri(), 'inspector')
) {
return new EventType(type: 'profiler');
}

return null;
}
}
6 changes: 3 additions & 3 deletions app/modules/Profiler/Application/EventHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
use Modules\Profiler\Application;
use Psr\Container\ContainerInterface;

class EventHandler implements Application\EventHandlerInterface
final readonly class EventHandler implements Application\EventHandlerInterface
{
/**
* @param class-string<\Modules\Sentry\Application\EventHandlerInterface>[] $handlers
*/
public function __construct(
private readonly ContainerInterface $container,
private readonly array $handlers
private ContainerInterface $container,
private array $handlers
) {
}

Expand Down
Loading
Loading