AI Review Center
Commit Review Workspace ?
Select a commit on the left to inspect quality, security, business value, findings, and suggested code changes.
Project AI Score
?
72%
Quality Avg
?
76%
Security Avg
?
67%
Reviews
?
16
Review Result ?
jattin01/safee-meet-backend · 20fe5f25
This commit adds a feature to store a deduplicated count of unique member searches, with full search history logging. It includes Eloquent models, a migration with proper constraints, and API controller methods to fetch recent searches and log searches atomically with upsert queries. The implementation improves the user experience by showing recent search data persistently server-side, reducing redundant data scanning. The code is generally well structured and uses Laravel conventions, but there are minor risks in raw SQL use without parameterized query builders and a lack of explicit error handling in logging.
Quality
?
85%
Security
?
75%
Business Value
?
90%
Maintainability
?
83%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Raw Db::statement With Manual Parameters
Where
app/Http/Controllers/MemberController.php:142
Issue / Evidence
raw DB::statement with manual parameters
Suggested Fix
use prepared statements or parameter binding consistently to improve security score
No Error Handling In Logsearch
Where
app/Http/Controllers/MemberController.php:130
Issue / Evidence
no error handling in logSearch
Suggested Fix
add try-catch and logging for failures to improve reliability and bug risk
Query Retrieves User Without Visibility Fi...
Where
app/Http/Controllers/MemberController.php:102
Issue / Evidence
query retrieves User without visibility filter
Suggested Fix
ensure user access rights are checked to improve security and business value
Cast Function Is Protected But Should Be P...
Where
app/Models/MemberSearchCount.php:15
Issue / Evidence
cast function is protected but should be public or property $casts used for Eloquent
Suggested Fix
adjust to conform to framework expectations for better quality
Missing Index On Search Count Or Last Sear...
Where
database/migrations/2026_07_26_150000_create_member_search_counts_table.php:30
Issue / Evidence
missing index on search_count or last_searched_at
Suggested Fix
consider additional indexes if query performance degrades to improve quality
Code Change Preview · app/Http/Controllers/Api/PinController.php
?
Removed / Before Commit
- <?php - - namespace App\Http\Controllers\Api; - - use App\Http\Controllers\Controller; - use App\Models\SearchHistory; - use App\Models\User; - use Illuminate\Http\JsonResponse; - use Illuminate\Http\Request; - - class PinController extends Controller - { - /** - * GET /api/search/pin/{pin} - * "Search Member" screen — SAFEE PIN tab. Logs to Recent Searches. - */ - public function findByPin(Request $request, string $pin): JsonResponse - {
Added / After Commit
Removed / Before Commit
- - namespace App\Http\Controllers; - - use App\Models\User; - use App\Support\Verification\VerificationLevelResolver; - use Illuminate\Http\JsonResponse; - use Illuminate\Http\Request; - - class MemberController extends Controller - { - ], 422); - } - - return response()->json([ - 'success' => true, - 'data' => $this->formatMember($user), - ], 422); - }
Added / After Commit
+ + namespace App\Http\Controllers; + + use App\Models\MemberSearchCount; + use App\Models\SearchHistory; + use App\Models\User; + use App\Support\Verification\VerificationLevelResolver; + use Illuminate\Http\JsonResponse; + use Illuminate\Http\Request; + use Illuminate\Support\Facades\DB; + + class MemberController extends Controller + { + ], 422); + } + + $this->logSearch($request, $user, $pin, 'pin'); +
Removed / Before Commit
Added / After Commit
+ <?php + + namespace App\Models; + + use Illuminate\Database\Eloquent\Model; + + class MemberSearchCount extends Model + { + protected $table = 'member_search_counts'; + + protected $fillable = [ + 'searcher_id', 'member_id', 'search_count', 'last_searched_at', + ]; + + protected function casts(): array + { + return [ + // Keep these string-shaped in API responses regardless of the
Removed / Before Commit
Added / After Commit
+ <?php + + namespace App\Models; + + use Illuminate\Database\Eloquent\Model; + + class SearchHistory extends Model + { + protected $table = 'search_history'; + + protected $fillable = [ + 'searcher_id', 'found_user_id', 'query', 'method', + ]; + + protected function casts(): array + { + return [ + // Keep these string-shaped in API responses regardless of the
Removed / Before Commit
- - Schema::create('search_history', function (Blueprint $table) { - $table->id(); - // users.id is a char(26) ULID on this deployment, not bigint. - $table->char('searcher_id', 26); - $table->foreign('searcher_id')->references('id')->on('users')->cascadeOnDelete(); - $table->char('found_user_id', 26)->nullable();
Added / After Commit
+ + Schema::create('search_history', function (Blueprint $table) { + $table->id(); + // This table already exists on production, so this Schema::create + // never actually runs there (guarded above) — kept only for fresh + // installs. NOTE: users.id was char(26) ULID when this migration + // was written; it was later converted to bigint auto-increment + // (see 02455bb.. / MigrateUsersToBigintId), and this table's + // searcher_id/found_user_id were migrated along with it. A fresh + // install today would need these as bigint unsigned, not char(26). + $table->char('searcher_id', 26); + $table->foreign('searcher_id')->references('id')->on('users')->cascadeOnDelete(); + $table->char('found_user_id', 26)->nullable();
Removed / Before Commit
Added / After Commit
+ <?php + + use Illuminate\Database\Migrations\Migration; + use Illuminate\Database\Schema\Blueprint; + use Illuminate\Support\Facades\Schema; + + return new class extends Migration + { + /** + * One row per (searcher, member) pair — repeat searches for the same + * member update this row instead of inserting a new one, so counts + * and "recently searched" ordering stay deduped at the DB level. + * Full per-search-attempt history (including the raw PIN/QR query + * text) is still logged separately in `search_history`. + */ + public function up(): void + { + if (Schema::hasTable('member_search_counts')) {
Removed / Before Commit
- \ No newline at end of file
Added / After Commit
+ { + "info": { + "_postman_id": "46ac2479-44ec-419f-8dba-3db3cbd6e4a7", + "name": "SafeeMeet API", + "description": "Full API collection for the SafeeMeet backend (Laravel + Sanctum).\n\nAuth: most endpoints require a Sanctum bearer token. Run one of the Auth requests first, then copy the returned `accessToken` into the `access_token` environment variable (the login/register/verify-otp requests do this automatically via a test script).\n\nBase URL is controlled by the `base_url` environment variable.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "variable": [
Removed / Before Commit
Added / After Commit
+ { + "id": "safeemeet-env-local", + "name": "SafeeMeet - Local/Production", + "values": [ + { "key": "base_url", "value": "http://168.144.112.102:8080/api", "type": "default", "enabled": true }, + { "key": "access_token", "value": "", "type": "secret", "enabled": true }, + { "key": "refresh_token", "value": "", "type": "secret", "enabled": true }, + { "key": "phone", "value": "+919999999999", "type": "default", "enabled": true }, + { "key": "otp", "value": "123456", "type": "default", "enabled": true }, + { "key": "meeting_id", "value": "1", "type": "default", "enabled": true }, + { "key": "review_id", "value": "1", "type": "default", "enabled": true }, + { "key": "incident_id", "value": "1", "type": "default", "enabled": true }, + { "key": "member_pin", "value": "SMHIPZTWPS", "type": "default", "enabled": true } + ], + "_postman_variable_scope": "environment" + }
Removed / Before Commit
- Route::prefix('members')->group(function (): void { - Route::get('search', [MemberController::class, 'searchByPin']); - Route::get('qr', [MemberController::class, 'searchByQR']); - }); - - Route::prefix('verification')->group(function (): void {
Added / After Commit
+ Route::prefix('members')->group(function (): void { + Route::get('search', [MemberController::class, 'searchByPin']); + Route::get('qr', [MemberController::class, 'searchByQR']); + Route::get('recent-searches', [MemberController::class, 'recentSearches']); + }); + + Route::prefix('verification')->group(function (): void {