Skip to content

Commit 7549d5a

Browse files
committed
refactor: Address Copilot review comments
- Extract HMAC_SHA256_OUTPUT_BYTES to shared tests/TestConstants.php - Remove fragile require_once from PersonTest - Create NormalizesPersonFields trait to avoid code duplication - Update PersonObserver and PersonRepository to use trait - Update Observer docblock: BYTEA → VARCHAR columns - Improve Binary cast docblock to explicitly mention PostgreSQL PDO All Copilot review comments addressed
1 parent 76919b4 commit 7549d5a

File tree

7 files changed

+62
-45
lines changed

7 files changed

+62
-45
lines changed

app/Casts/Binary.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
use Illuminate\Database\Eloquent\Model;
1313

1414
/**
15-
* Cast for binary data stored as base64 in VARCHAR columns.
15+
* Cast for binary data stored as base64 in VARCHAR columns to avoid PostgreSQL PDO BYTEA handling issues.
1616
*
17-
* Strategy: Store binary data as base64-encoded strings in VARCHAR for
18-
* reliable cross-database support, avoiding PDO binary binding issues.
17+
* Strategy: Store binary data as base64-encoded strings in VARCHAR columns for reliable cross-database support,
18+
* specifically to work around PostgreSQL PDO's handling of BYTEA columns and binary binding issues.
1919
*
2020
* - GET: Decode base64 from VARCHAR to raw binary
2121
* - SET: Encode raw binary to base64 for VARCHAR storage

app/Observers/PersonObserver.php

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@
1010

1111
use App\Models\Person;
1212
use App\Models\TenantKey;
13+
use App\Traits\NormalizesPersonFields;
1314

1415
/**
1516
* PersonObserver automatically computes blind indexes for encrypted fields.
1617
*
1718
* When a Person is created or updated, this observer:
1819
* 1. Normalizes plaintext values (email_plain, phone_plain)
1920
* 2. Generates HMAC-SHA256 blind indexes using the tenant's idx_key
20-
* 3. Stores indexes in *_idx BYTEA columns for equality search
21+
* 3. Stores indexes in *_idx VARCHAR columns for equality search
2122
*/
2223
class PersonObserver
2324
{
25+
use NormalizesPersonFields;
26+
2427
/**
2528
* Handle the Person "creating" event.
2629
*
@@ -63,24 +66,4 @@ private function updateBlindIndexes(Person $person): void
6366
$person->phone_idx = $tenantKey->generateBlindIndex($normalized);
6467
}
6568
}
66-
67-
/**
68-
* Normalize email for blind index generation.
69-
*
70-
* Removes whitespace and converts to lowercase.
71-
*/
72-
private function normalizeEmail(string $email): string
73-
{
74-
return strtolower(trim($email));
75-
}
76-
77-
/**
78-
* Normalize phone for blind index generation.
79-
*
80-
* Extracts only digits (removes spaces, dashes, parentheses).
81-
*/
82-
private function normalizePhone(string $phone): string
83-
{
84-
return preg_replace('/\D/', '', $phone) ?: '';
85-
}
8669
}

app/Repositories/PersonRepository.php

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use App\Models\Person;
1212
use App\Models\TenantKey;
13+
use App\Traits\NormalizesPersonFields;
1314

1415
/**
1516
* PersonRepository provides business logic for Person operations.
@@ -18,6 +19,8 @@
1819
*/
1920
class PersonRepository
2021
{
22+
use NormalizesPersonFields;
23+
2124
/**
2225
* Find a Person by email using blind index search.
2326
*
@@ -102,20 +105,4 @@ public function createOrUpdate(int $tenantId, array $attributes): Person
102105

103106
return $person;
104107
}
105-
106-
/**
107-
* Normalize email for blind index generation.
108-
*/
109-
private function normalizeEmail(string $email): string
110-
{
111-
return strtolower(trim($email));
112-
}
113-
114-
/**
115-
* Normalize phone for blind index generation.
116-
*/
117-
private function normalizePhone(string $phone): string
118-
{
119-
return preg_replace('/\D/', '', $phone) ?: '';
120-
}
121108
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* SPDX-FileCopyrightText: 2025 SecPal Contributors
5+
*
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace App\Traits;
10+
11+
/**
12+
* Trait for normalizing Person fields before blind index generation.
13+
*
14+
* Ensures consistent normalization across PersonObserver and PersonRepository.
15+
*/
16+
trait NormalizesPersonFields
17+
{
18+
/**
19+
* Normalize email for blind index generation.
20+
*
21+
* Removes whitespace and converts to lowercase.
22+
*/
23+
private function normalizeEmail(string $email): string
24+
{
25+
return strtolower(trim($email));
26+
}
27+
28+
/**
29+
* Normalize phone for blind index generation.
30+
*
31+
* Extracts only digits (removes spaces, dashes, parentheses).
32+
*/
33+
private function normalizePhone(string $phone): string
34+
{
35+
return preg_replace('/\D/', '', $phone) ?: '';
36+
}
37+
}

tests/Feature/PersonTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
use App\Models\TenantKey;
1111
use Illuminate\Foundation\Testing\RefreshDatabase;
1212

13-
// Import constant from TenantKeyTest
14-
require_once __DIR__.'/TenantKeyTest.php';
13+
// HMAC_SHA256_OUTPUT_BYTES is 32 (SHA-256 output size in bytes)
14+
require_once __DIR__.'/../TestConstants.php';
1515

1616
uses(RefreshDatabase::class);
1717

tests/Feature/TenantKeyTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
use App\Models\TenantKey;
1010
use Illuminate\Foundation\Testing\RefreshDatabase;
1111

12-
uses(RefreshDatabase::class);
12+
// HMAC_SHA256_OUTPUT_BYTES is 32 (SHA-256 output size in bytes)
13+
require_once __DIR__.'/../TestConstants.php';
1314

14-
// SHA-256 produces 32 bytes output
15-
const HMAC_SHA256_OUTPUT_BYTES = 32;
15+
uses(RefreshDatabase::class);
1616

1717
/**
1818
* Helper function to clean up the KEK file.

tests/TestConstants.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
/*
4+
* SPDX-FileCopyrightText: 2025 SecPal Contributors
5+
*
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
// SHA-256 produces 32 bytes output
10+
const HMAC_SHA256_OUTPUT_BYTES = 32;

0 commit comments

Comments
 (0)