fix(projects): Plan 5 Task 3 code-review fixes (2 Important + 2 Minor)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-11 18:38:52 +03:00
parent 9d2e7270de
commit 2ffbb49faa
4 changed files with 21 additions and 3 deletions
@@ -28,13 +28,13 @@ class StoreProjectRequest extends FormRequest
];
if ($signalType === 'site') {
$base['signal_identifier'] = ['required', 'string', 'regex:/^[a-z0-9.\-]+\.[a-z]{2,}$/i'];
$base['signal_identifier'] = ['required', 'string', 'regex:/^[a-z0-9][a-z0-9\-]*(\.[a-z0-9][a-z0-9\-]*)*\.[a-z]{2,}$/i'];
} elseif ($signalType === 'call') {
$base['signal_identifier'] = ['required', 'string', 'regex:/^7\d{10}$/'];
} elseif ($signalType === 'sms') {
$base['sms_senders'] = ['required', 'array', 'min:1'];
$base['sms_senders.*'] = ['string', 'max:11'];
$base['sms_keyword'] = ['nullable', 'string', 'max:50'];
$base['sms_keyword'] = ['nullable', 'string', 'min:1', 'max:50'];
}
return $base;
@@ -16,6 +16,9 @@ return new class extends Migration
{
public function up(): void
{
if (Schema::hasColumn('tenants', 'limits')) {
return;
}
Schema::table('tenants', function (Blueprint $table) {
// limits JSONB: {"max_users":5,"max_projects":10,"api_rps":60}
// Аналог limits в tariff_plans — per-tenant override лимитов тарифа.
+1 -1
View File
@@ -867,7 +867,7 @@ parameters:
-
message: '#^Call to an undefined method Pest\\PendingCalls\\TestCall\:\:actingAs\(\)\.$#'
identifier: method.notFound
count: 8
count: 9
path: tests/Feature/Plan5/Projects/ProjectsStoreTest.php
-
@@ -25,6 +25,7 @@ it('creates a site project with valid payload', function () {
]);
$response->assertCreated();
$response->assertJsonPath('data.sync_status', 'pending');
expect(Project::where('signal_identifier', 'okna-spb.ru')->exists())->toBeTrue();
Queue::assertPushed(SyncSupplierProjectJob::class);
});
@@ -129,3 +130,17 @@ it('forces tenant_id from auth user (not from payload)', function () {
$project = Project::where('signal_identifier', 'x.ru')->latest()->first();
expect($project->tenant_id)->toBe($tenantA->id);
});
it('rejects site domain with consecutive dots', function () {
$tenant = Tenant::factory()->create();
$user = User::factory()->create(['tenant_id' => $tenant->id]);
$response = $this->actingAs($user)->postJson('/api/projects', [
'name' => 'X', 'signal_type' => 'site', 'signal_identifier' => 'okna..spb.ru',
'daily_limit_target' => 50, 'region_mask' => 0, 'region_mode' => 'include',
'delivery_days_mask' => 127,
]);
$response->assertStatus(422);
$response->assertJsonValidationErrors(['signal_identifier']);
});