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
Prev Previous commit
Next Next commit
Code refactoring
Fixes unit tests
  • Loading branch information
butschster committed Apr 27, 2024
commit 75bfbe0f64e8a39900db7880341a40669ea6d6a9
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ protoc-gen-php-grpc*
.phpunit.result.cache
.php-cs-fixer.cache
.deptrac.cache
.phpunit.cache
8 changes: 5 additions & 3 deletions app/config/queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
use Spiral\RoadRunner\Jobs\Queue\MemoryCreateInfo;
use Spiral\RoadRunnerBridge\Queue\Queue;

$defaultConnection = env('QUEUE_DEFAULT_CONNECTION', 'roadrunner');

return [
'default' => env('QUEUE_CONNECTION', 'sync'),
'default' => env('QUEUE_CONNECTION', 'memory'),
'aliases' => [
'webhook' => 'roadrunner',
'events' => 'roadrunner',
'webhook' => $defaultConnection,
'events' => $defaultConnection,
],
'pipelines' => [
'memory' => [
Expand Down
3 changes: 3 additions & 0 deletions app/modules/Events/Domain/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
use App\Application\Domain\ValueObjects\Uuid;
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\Annotated\Annotation\Table\Index;

#[Entity(
repository: EventRepositoryInterface::class
)]
#[Index(columns: ['type'])]
#[Index(columns: ['project'])]
class Event
{
/** @internal */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private function listenEvent(ServerRequestInterface $request): ?EventType
|| $request->hasHeader('X-Inspector-Version')
|| \str_ends_with((string)$request->getUri(), 'inspector')
) {
return new EventType(type: 'profiler');
return new EventType(type: 'inspector');
}

return null;
Expand Down
15 changes: 2 additions & 13 deletions app/modules/Projects/Application/ProjectFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,12 @@

use Modules\Projects\Domain\Project;
use Modules\Projects\Domain\ProjectFactoryInterface;
use Modules\Projects\Exception\InvalidKeyFormatException;
use Modules\Projects\Domain\ValueObject\Key;

final readonly class ProjectFactory implements ProjectFactoryInterface
{
public function __construct(
private string $allowedKeyCharacters = 'a-z0-9-_',
) {
}

public function create(string $key, string $name): Project
public function create(Key $key, string $name): Project
{
if (\preg_match('/^[' . $this->allowedKeyCharacters . ']+$/', $key) !== 1) {
throw new InvalidKeyFormatException(
'Invalid project key. Key must contain only lowercase letters, numbers, hyphens and underscores.',
);
}

return new Project($key, $name);
}
}
3 changes: 2 additions & 1 deletion app/modules/Projects/Application/YamlFileProjectLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Modules\Projects\Domain\ProjectFactoryInterface;
use Modules\Projects\Domain\ProjectLocatorInterface;
use Modules\Projects\Domain\ValueObject\Key;
use Psr\Log\LoggerInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Yaml;
Expand Down Expand Up @@ -36,7 +37,7 @@ public function findAll(): iterable
$this->validateData($data);

$project = $this->projectFactory->create(
key: $data['project']['key'],
key: Key::create($data['project']['key']),
name: $data['project']['name'],
);

Expand Down
8 changes: 4 additions & 4 deletions app/modules/Projects/Domain/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace Modules\Projects\Domain;

use App\Application\Domain\ValueObjects\Uuid;
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Modules\Projects\Domain\ValueObject\Key;

#[Entity(
repository: ProjectRepositoryInterface::class
Expand All @@ -15,15 +15,15 @@ class Project
{
/** @internal */
public function __construct(
#[Column(type: 'string(36)', primary: true)]
private string $key,
#[Column(type: 'string(36)', primary: true, typecast: Key::class)]
private Key $key,

#[Column(type: 'string')]
private string $name,
) {
}

public function getKey(): string
public function getKey(): Key
{
return $this->key;
}
Expand Down
4 changes: 3 additions & 1 deletion app/modules/Projects/Domain/ProjectFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Modules\Projects\Domain;

use Modules\Projects\Domain\ValueObject\Key;

interface ProjectFactoryInterface
{
public function create(string $key, string $name): Project;
public function create(Key $key, string $name): Project;
}
69 changes: 69 additions & 0 deletions app/modules/Projects/Domain/ValueObject/Key.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace Modules\Projects\Domain\ValueObject;

use App\Application\Domain\Assert;

final readonly class Key implements \JsonSerializable, \Stringable
{
public const MIN_LENGTH = 3;
public const MAX_LENGTH = 36;
public const ALLOWED_CHARACTERS = 'a-z0-9-_';

public static function create(string $key): self
{
Assert::notEmpty(
value: $key,
message: 'Project key is required.',
);

Assert::minLength(
value: $key,
min: self::MIN_LENGTH,
message: 'Invalid project key. Key must be at least 3 characters long.',
);

Assert::maxLength(
value: $key,
max: self::MAX_LENGTH,
message: 'Invalid project key. Key must be less than 36 characters long.',
);

Assert::regex(
value: $key,
pattern: '/^[' . self::ALLOWED_CHARACTERS . ']+$/',
message: 'Invalid project key. Key must contain only lowercase letters, numbers, hyphens and underscores.',
);

return new self($key);
}

/**
* @internal
* @private
*/
public function __construct(
public string $value,
) {
}

/**
* Create from data storage raw value
*/
final public static function typecast(mixed $value): self
{
return new self($value);
}

public function jsonSerialize(): string
{
return $this->value;
}

public function __toString(): string
{
return $this->value;
}
}
16 changes: 7 additions & 9 deletions app/modules/Sentry/Application/SecretKeyValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __construct(

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

Expand All @@ -29,14 +29,12 @@ public function validateRequest(ServerRequestInterface $request): bool
return false;
}

$key = null;
$parts = \explode(',', $request->getHeaderLine('X-Sentry-Auth'));
foreach ($parts as $part) {
if (\str_starts_with($part, 'sentry_key=')) {
$key = \substr($part, 11);
break;
}
}
// Header: Sentry sentry_version=7, sentry_client=raven-php/0.15.0, sentry_key=1234567890
$key = \preg_match(
'/sentry_key=(\w+)/',
$request->getHeaderLine('X-Sentry-Auth'),
$matches,
) ? $matches[1] : null;

return $this->secret === $key;
}
Expand Down
20 changes: 14 additions & 6 deletions app/modules/Sentry/Interfaces/Http/JavascriptAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,22 @@
use Spiral\Boot\EnvironmentInterface;
use Spiral\Router\Annotation\Route;

final class JavascriptAction
final readonly class JavascriptAction
{
#[Route(route: '/sentry/<id>.js', name: 'sentry.js', methods: 'GET', group: 'api')]
public function __invoke(EnvironmentInterface $env, mixed $id): ResponseInterface
#[Route(route: '/sentry/<project>.js', name: 'sentry.js', methods: 'GET', group: 'api')]
public function __invoke(EnvironmentInterface $env, string $project): ResponseInterface
{
$jsSdkUrl = $env->get('SENTRY_JS_SDK_URL', 'https://browser.sentry-cdn.com/7.69.0/bundle.tracing.replay.min.js');
$host = $env->get('SENTRY_DSN_HOST', 'http:https://[email protected]:8000');
$url = \rtrim($host, '/') . '/' . $id;
$jsSdkUrl = $env->get(
'SENTRY_JS_SDK_URL',
'https://browser.sentry-cdn.com/7.69.0/bundle.tracing.replay.min.js',
);

$host = $env->get(
'SENTRY_JS_DSN_HOST',
'http:https://[email protected]:8000',
);

$url = \rtrim($host, '/') . '/' . $project;

return new Response(
status: 200,
Expand Down
11 changes: 6 additions & 5 deletions app/modules/Smtp/Application/Mail/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use ZBateson\MailMimeParser\Header\AddressHeader;
use ZBateson\MailMimeParser\Header\Part\AddressPart;
use ZBateson\MailMimeParser\Message as ParseMessage;
use ZBateson\MailMimeParser\Message\IMessagePart;

final readonly class Parser
{
Expand Down Expand Up @@ -51,20 +52,20 @@ public function parse(string $body, array $allRecipients = []): Message
$this->storage->bucket('attachments'),
$message->getHeader('Message - Id')?->getValue(),
$body, $from, $recipients, $ccs, $subject,
$html, $text, $replyTo, $allRecipients, $attachments
$html, $text, $replyTo, $allRecipients, $attachments,
);
}

/**
* @param MessagePart[] $attachments
* @param ParseMessage\IMessagePart[] $attachments
* @return Attachment[]
*/
private function buildAttachmentFrom(array $attachments): array
{
return \array_map(fn(MessagePart|ParseMessage\MimePart $part) => new Attachment(
return \array_map(fn(ParseMessage\IMessagePart $part) => new Attachment(
$part->getFilename(),
$part->getContent(),
$part->getContentType()
$part->getContentType(),
), $attachments);
}

Expand All @@ -74,7 +75,7 @@ private function buildAttachmentFrom(array $attachments): array
*/
private function joinNameAndEmail(array $addresses): array
{
return array_map(function (AddressPart $addressPart) {
return \array_map(function (AddressPart $addressPart) {
$name = $addressPart->getName();
$email = $addressPart->getValue();

Expand Down
9 changes: 5 additions & 4 deletions app/modules/VarDumper/Application/Dump/MessageParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Modules\VarDumper\Application\Dump;

use Modules\VarDumper\Exception\InvalidPayloadException;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Cloner\Stub;

Expand All @@ -12,13 +13,13 @@ final class MessageParser
/**
* @throws \RuntimeException
*/
public function parse(string $message): array
public function parse(string $message): ParsedPayload
{
$payload = @\unserialize(\base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]);

// Impossible to decode the message, give up.
if (false === $payload) {
throw new \RuntimeException("Unable to decode a message from var-dumper client.");
throw new InvalidPayloadException("Unable to decode the message.");
}

if (
Expand All @@ -27,9 +28,9 @@ public function parse(string $message): array
|| !$payload[0] instanceof Data
|| !\is_array($payload[1])
) {
throw new \RuntimeException("Invalid var-dumper payload.");
throw new InvalidPayloadException("Invalid payload structure.");
}

return $payload;
return new ParsedPayload(data: $payload[0], context: $payload[1]);
}
}
16 changes: 16 additions & 0 deletions app/modules/VarDumper/Application/Dump/ParsedPayload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Modules\VarDumper\Application\Dump;

use Symfony\Component\VarDumper\Cloner\Data;

final readonly class ParsedPayload
{
public function __construct(
public Data $data,
public array $context,
) {
}
}
10 changes: 10 additions & 0 deletions app/modules/VarDumper/Exception/InvalidPayloadException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Modules\VarDumper\Exception;

final class InvalidPayloadException extends VarDumperException
{

}
10 changes: 10 additions & 0 deletions app/modules/VarDumper/Exception/VarDumperException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Modules\VarDumper\Exception;

class VarDumperException extends \DomainException
{

}
Loading
Loading