Files
jabali-panel/routes/api.php
2026-01-24 19:36:46 +02:00

166 lines
5.4 KiB
PHP

<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Cache;
use App\Services\Agent\AgentClient;
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Route::post('/phpmyadmin/verify-token', function (Request $request) {
$token = $request->input('token');
// Use Cache::get() which handles the prefix automatically
$data = Cache::get('phpmyadmin_token_' . $token);
if (!$data) {
return response()->json(['error' => 'Invalid token'], 401);
}
// Delete token after use (single use)
Cache::forget('phpmyadmin_token_' . $token);
return response()->json($data);
});
// Internal API for jabali-cache WordPress plugin
Route::post('/internal/page-cache', function (Request $request) {
// Only allow requests from localhost
$clientIp = $request->ip();
if (!in_array($clientIp, ['127.0.0.1', '::1', 'localhost'])) {
return response()->json(['error' => 'Forbidden'], 403);
}
$domain = $request->input('domain');
$enabled = $request->boolean('enabled');
$secret = $request->input('secret');
if (empty($domain)) {
return response()->json(['error' => 'Domain is required'], 400);
}
// Validate secret matches what's in wp-config.php
// The secret is the first 32 chars of AUTH_KEY from wp-config
if (empty($secret) || strlen($secret) < 16) {
return response()->json(['error' => 'Invalid secret'], 401);
}
// Find the user who owns this domain
$user = \App\Models\User::whereHas('domains', function ($query) use ($domain) {
$query->where('domain', $domain);
})->first();
if (!$user) {
return response()->json(['error' => 'Domain not found'], 404);
}
// Verify the secret by checking wp-config.php
$wpConfigPath = "/home/{$user->username}/domains/{$domain}/public_html/wp-config.php";
if (!file_exists($wpConfigPath)) {
return response()->json(['error' => 'WordPress not found'], 404);
}
$wpConfig = file_get_contents($wpConfigPath);
if (preg_match("/define\s*\(\s*['\"]AUTH_KEY['\"]\s*,\s*['\"]([^'\"]+)['\"]\s*\)/", $wpConfig, $matches)) {
$authKey = $matches[1];
$expectedSecret = substr(md5($authKey), 0, 32);
if ($secret !== $expectedSecret) {
return response()->json(['error' => 'Invalid secret'], 401);
}
} else {
return response()->json(['error' => 'Cannot verify secret'], 401);
}
try {
$agent = new AgentClient();
if ($enabled) {
$result = $agent->send('wp.page_cache_enable', [
'username' => $user->username,
'domain' => $domain,
]);
} else {
$result = $agent->send('wp.page_cache_disable', [
'username' => $user->username,
'domain' => $domain,
]);
}
return response()->json($result);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
});
// Internal API for smart page cache purging (called by jabali-cache WordPress plugin)
Route::post('/internal/page-cache-purge', function (Request $request) {
// Only allow requests from localhost
$clientIp = $request->ip();
if (!in_array($clientIp, ['127.0.0.1', '::1', 'localhost'])) {
return response()->json(['error' => 'Forbidden'], 403);
}
$domain = $request->input('domain');
$paths = $request->input('paths', []);
$purgeAll = $request->boolean('purge_all');
$secret = $request->input('secret');
if (empty($domain)) {
return response()->json(['error' => 'Domain is required'], 400);
}
// Validate secret matches what's in wp-config.php
if (empty($secret) || strlen($secret) < 16) {
return response()->json(['error' => 'Invalid secret'], 401);
}
// Find the user who owns this domain
$user = \App\Models\User::whereHas('domains', function ($query) use ($domain) {
$query->where('domain', $domain);
})->first();
if (!$user) {
return response()->json(['error' => 'Domain not found'], 404);
}
// Verify the secret by checking wp-config.php
$wpConfigPath = "/home/{$user->username}/domains/{$domain}/public_html/wp-config.php";
if (!file_exists($wpConfigPath)) {
return response()->json(['error' => 'WordPress not found'], 404);
}
$wpConfig = file_get_contents($wpConfigPath);
if (preg_match("/define\s*\(\s*['\"]AUTH_KEY['\"]\s*,\s*['\"]([^'\"]+)['\"]\s*\)/", $wpConfig, $matches)) {
$authKey = $matches[1];
$expectedSecret = substr(md5($authKey), 0, 32);
if ($secret !== $expectedSecret) {
return response()->json(['error' => 'Invalid secret'], 401);
}
} else {
return response()->json(['error' => 'Cannot verify secret'], 401);
}
try {
$agent = new AgentClient();
if ($purgeAll || empty($paths)) {
// Purge entire domain cache
$result = $agent->send('wp.page_cache_purge', [
'domain' => $domain,
]);
} else {
// Purge specific paths
$result = $agent->send('wp.page_cache_purge', [
'domain' => $domain,
'paths' => $paths,
]);
}
return response()->json($result);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
});