This commit is contained in:
pbao9
2026-02-10 17:27:10 +07:00
parent 3ece85430c
commit a36802bd82
8 changed files with 208 additions and 126 deletions
+3 -1
View File
@@ -68,6 +68,8 @@ class Kernel extends HttpKernel
'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,
'CustomerLoginCheck' => \App\Http\Middleware\CustomerLoginCheck::class,
'IsLoginCheck' => \App\Http\Middleware\IsLoginCheck::class,
'Staff' => \App\Http\Middleware\StaffCheck::class
'Staff' => \App\Http\Middleware\StaffCheck::class,
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
'api.auth' => \App\Http\Middleware\ApiAuthCheck::class,
];
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ApiAuthCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, $guard = null)
{
$checkGuard = $guard ?: 'sanctum';
if (!Auth::guard($checkGuard)->check()) {
return response()->json([
'error' => true,
'message' => 'Unauthorized. Access Denied.',
'data' => [],
'code' => 401
], 401);
}
return $next($request);
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceJsonResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
+10 -2
View File
@@ -38,11 +38,19 @@ class RouteServiceProvider extends ServiceProvider
$this->configureRateLimiting();
$this->routes(function () {
Route::domain('api-agency.tgs.com.vn')
->middleware('api')
// 1. Agency API (Domain riêng, dùng routes/client.php)
Route::domain('api-agency.tgs.com.vn.test')
->middleware(['api', 'json.response'])
->namespace($this->namespace)
->group(base_path('routes/client.php'));
// 2. System API (Dùng cho portal.test/api/..., dùng routes/api.php)
Route::prefix('api')
->middleware(['api', 'json.response'])
->namespace($this->namespace)
->group(base_path('routes/api.php'));
// 3. Web & Admin routes
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
@@ -1,130 +1,130 @@
@php
$selectedDatacenterId = old('module_datacenter_id');
$selectedDatacenterId = old('module_datacenter_id');
if (!$selectedDatacenterId && $model) {
if ($model instanceof \App\Models\ModuleDatacenter) {
$selectedDatacenterId = $model->id;
} elseif ($model instanceof \App\Models\ModuleHost || $model instanceof \App\Models\ModuleFolder) {
$selectedDatacenterId = $model->module_datacenter_id;
} elseif ($model instanceof \App\Models\ModuleDatastore || $model instanceof \App\Models\ModuleNetwork) {
$selectedDatacenterId = $model->host?->module_datacenter_id;
} elseif ($model instanceof \App\Models\ModuleIpAddress) {
$selectedDatacenterId = $model->host?->module_datacenter_id;
} elseif (isset($model->module_datacenter_id)) {
$selectedDatacenterId = $model->module_datacenter_id;
} elseif (method_exists($model, 'host') && $model->host) {
$selectedDatacenterId = $model->host->module_datacenter_id;
}
if (!$selectedDatacenterId && $model) {
if ($model instanceof \App\Models\ModuleDatacenter) {
$selectedDatacenterId = $model->id;
} elseif ($model instanceof \App\Models\ModuleHost || $model instanceof \App\Models\ModuleFolder) {
$selectedDatacenterId = $model->module_datacenter_id;
} elseif ($model instanceof \App\Models\ModuleDatastore || $model instanceof \App\Models\ModuleNetwork) {
$selectedDatacenterId = $model->host?->module_datacenter_id;
} elseif ($model instanceof \App\Models\ModuleIpAddress) {
$selectedDatacenterId = $model->host?->module_datacenter_id;
} elseif (isset($model->module_datacenter_id)) {
$selectedDatacenterId = $model->module_datacenter_id;
} elseif (method_exists($model, 'host') && $model->host) {
$selectedDatacenterId = $model->host->module_datacenter_id;
}
}
@endphp
<div class="row form-group align-items-center mb-0">
<label for="datacenter_id" class="col-md-3 text-right">Chọn Datacenter</label>
<div class="col-md-9 p-1 bg-customer">
<select class="form-control select2 single__select datacenter_id" name="module_datacenter_id"
data-selected="{{ $selectedDatacenterId }}" data-placeholder="--- Chọn Datacenter ---">
</select>
</div>
<div class="row form-group align-items-center mb-0">
<label for="datacenter_id" class="col-md-3 text-right">Chọn Datacenter</label>
<div class="col-md-9 p-1 bg-customer">
<select class="form-control select2 single__select datacenter_id" name="module_datacenter_id"
data-selected="{{ $selectedDatacenterId }}" data-placeholder="--- Chọn Datacenter ---">
</select>
</div>
@push('custom-scripts')
<script>
$(document).ready(function () {
// Prevent multiple initializations using namespace
if (window.datacenterComponentInitialized) {
</div>
@push('custom-scripts')
<script>
$(document).ready(function () {
// Prevent multiple initializations using namespace
if (window.datacenterComponentInitialized) {
return;
}
window.datacenterComponentInitialized = true;
const $vcenter = $('.vcenter_id');
const $datacenter = $('.datacenter_id');
const $host = $('.host_id');
// Debounce function to prevent spam API calls
let loadDatacentersTimeout;
function debounceLoadDatacenters(vcenterId, preselect = null) {
clearTimeout(loadDatacentersTimeout);
loadDatacentersTimeout = setTimeout(() => {
loadDatacenters(vcenterId, preselect);
}, 300); // 300ms debounce
}
function loadDatacenters(vcenterId, preselect = null) {
// Check if already loading to prevent duplicate calls
if ($datacenter.prop('disabled') && $datacenter.find('option:first').text().includes('Đang tải')) {
return;
}
window.datacenterComponentInitialized = true;
const $vcenter = $('.vcenter_id');
const $datacenter = $('.datacenter_id');
const $host = $('.host_id');
// Debounce function to prevent spam API calls
let loadDatacentersTimeout;
function debounceLoadDatacenters(vcenterId, preselect = null) {
clearTimeout(loadDatacentersTimeout);
loadDatacentersTimeout = setTimeout(() => {
loadDatacenters(vcenterId, preselect);
}, 300); // 300ms debounce
if (!vcenterId) {
$datacenter.html('<option value="">--- Chọn Datacenter ---</option>').prop('disabled', true);
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
return;
}
function loadDatacenters(vcenterId, preselect = null) {
// Check if already loading to prevent duplicate calls
if ($datacenter.prop('disabled') && $datacenter.find('option:first').text().includes('Đang tải')) {
return;
}
$datacenter.html('<option value="">Đang tải Datacenter...</option>').prop('disabled', true);
if (!vcenterId) {
$datacenter.html('<option value="">--- Chọn Datacenter ---</option>').prop('disabled', true);
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
return;
}
$.ajax({
url: '{{ route('api.getDatacenter') }}',
type: 'GET',
data: {
vcenter: vcenterId
},
success: function (response) {
if (!response.error && response.data.length > 0) {
let options = '<option value="">--- Chọn Datacenter ---</option>';
response.data.forEach(dc => {
const selected = preselect == dc.id ? 'selected' : '';
options +=
`<option value="${dc.id}" ${selected}>${dc.name} - ${dc.datacenter_id}</option>`;
});
$datacenter.html(options).prop('disabled', false);
$datacenter.html('<option value="">Đang tải Datacenter...</option>').prop('disabled', true);
$.ajax({
url: '{{ route('api.getDatacenter') }}',
type: 'GET',
data: {
vcenter: vcenterId
},
success: function (response) {
if (!response.error && response.data.length > 0) {
let options = '<option value="">--- Chọn Datacenter ---</option>';
response.data.forEach(dc => {
const selected = preselect == dc.id ? 'selected' : '';
options +=
`<option value="${dc.id}" ${selected}>${dc.name} - ${dc.datacenter_id}</option>`;
});
$datacenter.html(options).prop('disabled', false);
// If there's a preselected datacenter ID, select it
if (preselect) {
setTimeout(() => {
$datacenter.val(preselect).trigger('change');
}, 100);
}
} else {
$datacenter.html('<option value="">Không tìm thấy Datacenter</option>')
.prop('disabled', true);
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
// If there's a preselected datacenter ID, select it
if (preselect) {
setTimeout(() => {
$datacenter.val(preselect).trigger('change');
}, 100);
}
},
error: function () {
$datacenter.html('<option value="">Lỗi tải datacenter</option>').prop('disabled', true);
} else {
$datacenter.html('<option value="">Không tìm thấy Datacenter</option>')
.prop('disabled', true);
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
}
});
}
// Remove existing event handlers and bind new ones with namespace
$vcenter.off('change.datacenterComponent').on('change.datacenterComponent', function () {
const vcenterId = $(this).val();
debounceLoadDatacenters(vcenterId);
});
// When datacenter changes
$datacenter.off('change.datacenterComponent').on('change.datacenterComponent', function () {
const datacenterId = $(this).val();
// Reset and disable host
},
error: function () {
$datacenter.html('<option value="">Lỗi tải datacenter</option>').prop('disabled', true);
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
}
});
}
// Enable host if datacenter is selected
if (datacenterId) {
$host.prop('disabled', false);
}
});
// Remove existing event handlers and bind new ones with namespace
$vcenter.off('change.datacenterComponent').on('change.datacenterComponent', function () {
const vcenterId = $(this).val();
debounceLoadDatacenters(vcenterId);
});
// Initial load logic
const selectedDatacenterId = $datacenter.data('selected');
if ($vcenter.val() && selectedDatacenterId) {
debounceLoadDatacenters($vcenter.val(), selectedDatacenterId);
} else if ($vcenter.val()) {
// If only vcenter is selected, load datacenters without preselection
debounceLoadDatacenters($vcenter.val());
// When datacenter changes
$datacenter.off('change.datacenterComponent').on('change.datacenterComponent', function () {
const datacenterId = $(this).val();
// Reset and disable host
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
// Enable host if datacenter is selected
if (datacenterId) {
$host.prop('disabled', false);
}
});
</script>
@endpush
// Initial load logic
const selectedDatacenterId = $datacenter.data('selected');
if ($vcenter.val() && selectedDatacenterId) {
debounceLoadDatacenters($vcenter.val(), selectedDatacenterId);
} else if ($vcenter.val()) {
// If only vcenter is selected, load datacenters without preselection
debounceLoadDatacenters($vcenter.val());
}
});
</script>
@endpush
@@ -1,9 +1,9 @@
@php
$selectedVcenterId = old('vcenter_id') ??
($model?->host?->datacenter?->vcenter_id ?? (
$model?->ipaddress?->host?->datacenter?->vcenter?->id ??
$model?->vcenter_id ?? null
));
$selectedVcenterId = old('vcenter_id') ??
($model?->host?->datacenter?->vcenter_id ?? (
$model?->ipaddress?->host?->datacenter?->vcenter?->id ??
$model?->vcenter_id ?? null
));
@endphp
<div class="row form-group align-items-center mb-0">
@@ -64,5 +64,5 @@
if ($datacenter.is('select')) $datacenter.prop('disabled', false);
}
});
</script>
</script>
@endpush
+2 -7
View File
@@ -44,12 +44,11 @@ use Illuminate\Support\Str;
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::get('/', fn() => response()->json(['api' => 'ok']));
Route::prefix('v1')
/* Api for Admin */
->group(function () {
Route::prefix('system')->middleware(['auth:sanctum'])->group(function () {
Route::prefix('system')->middleware(['api.auth'])->group(function () {
Route::controller(ModuleController::class)->group(function () {
Route::get('get-list-vcenter', 'getVCenter')->name('api.getVCenter');
Route::get('get-list-datacenter', 'getDatacenter')->name('api.getDatacenter');
@@ -60,10 +59,6 @@ Route::prefix('v1')
Route::get('get-list-version-os', 'getOsServerVersion')->name('api.getVersion');
Route::get('get-list-os-group', 'getOsGroup')->name('api.getOsGroup');
});
Route::get('test-ssh-connection', function (ServiceVCenter $serviceVCenter) {
Log::info('🧪 API Test SSH Connection - Starting test via route');
return response()->json($serviceVCenter->testSSHConnection());
})->name('api.testSSHConnection');
Route::post('rebuild-vps', [\App\Http\Controllers\Api\VpsActionController::class, 'rebuildVps'])
->name('api.system.rebuildVps');
@@ -463,7 +458,7 @@ Route::prefix('v1')
})
/* Api for customer */
->group(function () {
Route::middleware(['auth:sanctum'])
Route::middleware(['api.auth'])
->group(function () {
Route::post('get-status-virtual-machine', function (Request $request, ServiceVCenter $serviceVCenter) {
$vmware_id = $request->vmware_id;
+21
View File
@@ -0,0 +1,21 @@
<?php
use App\Models\Product;
Route::prefix('v1')->group(function () {
Route::get('get-list-product', function () {
return response()->json([
'error' => false,
'data' => Product::all()
]);
})->name('api.user.GetListProduct');
});
Route::any('{any}', function () {
return response()->json([
'error' => true,
'message' => 'API Route not found'
], 404);
})->where('any', '.*');