update
This commit is contained in:
@@ -1,39 +1,46 @@
|
||||
name: Deploy Portal
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- production
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
deploy:
|
||||
name: Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy via SSH
|
||||
uses: appleboy/ssh-action@v1.2.0
|
||||
with:
|
||||
host: ${{ secrets.HOST }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
port: ${{ secrets.PORT }}
|
||||
script_stop: true
|
||||
script: |
|
||||
set -e
|
||||
cd ${{ secrets.PROJECT_PATH }}
|
||||
steps:
|
||||
- name: Deploy via SSH
|
||||
uses: appleboy/ssh-action@v1.2.0
|
||||
with:
|
||||
host: ${{ secrets.HOST }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
port: ${{ secrets.PORT }}
|
||||
script_stop: true
|
||||
script: |
|
||||
set -e
|
||||
DEPLOY_PATH="/var/www/vhosts/api.portal.tgs.com.vn/httpdocs"
|
||||
REPO_URL="${{ secrets.REPO_URL }}"
|
||||
|
||||
echo "Pulling latest code..."
|
||||
git pull origin main
|
||||
if [ ! -d "$DEPLOY_PATH/.git" ]; then
|
||||
echo "First deploy - cloning repository..."
|
||||
git clone -b product "$REPO_URL" "$DEPLOY_PATH"
|
||||
else
|
||||
echo "Pulling latest code..."
|
||||
cd "$DEPLOY_PATH"
|
||||
git pull origin product
|
||||
fi
|
||||
|
||||
echo "Installing dependencies..."
|
||||
composer install --no-dev --optimize-autoloader --no-interaction --no-progress
|
||||
echo "Installing dependencies..."
|
||||
composer install --no-dev --optimize-autoloader --no-interaction --no-progress
|
||||
|
||||
echo "Running migrations..."
|
||||
php artisan migrate --force
|
||||
echo "Running migrations..."
|
||||
php artisan migrate --force
|
||||
|
||||
echo "Optimizing..."
|
||||
php artisan optimize
|
||||
echo "Optimizing..."
|
||||
php artisan optimize
|
||||
|
||||
echo "Deploy completed."
|
||||
echo "Deploy completed."
|
||||
|
||||
+103
-41
@@ -2,79 +2,141 @@
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
use Illuminate\Session\TokenMismatchException;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array<int, class-string<Throwable>>
|
||||
*/
|
||||
protected $dontReport = [
|
||||
//
|
||||
];
|
||||
protected $dontReport = [];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
public function render($request, Throwable $e)
|
||||
{
|
||||
// Duplicate constraint
|
||||
$this->renderable(function (QueryException $e, $request) {
|
||||
if ($request->is('api/*') || $request->is('v1/*') || $request->expectsJson()) {
|
||||
return $this->renderApiException($request, $e);
|
||||
}
|
||||
|
||||
if ($e->errorInfo[1] == 1062) {
|
||||
return parent::render($request, $e);
|
||||
}
|
||||
|
||||
protected function unauthenticated($request, AuthenticationException $exception)
|
||||
{
|
||||
if ($request->is('api/*') || $request->is('v1/*') || $request->expectsJson()) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'status' => 401,
|
||||
'message' => 'Bạn chưa đăng nhập hoặc phiên đăng nhập đã hết hạn.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
return redirect()->guest($exception->redirectTo() ?? route('login'));
|
||||
}
|
||||
|
||||
private function renderApiException($request, Throwable $e)
|
||||
{
|
||||
if ($e instanceof TokenMismatchException) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'status' => 419,
|
||||
'message' => 'Phiên làm việc đã hết hạn, vui lòng thử lại.',
|
||||
], 419);
|
||||
}
|
||||
|
||||
if ($e instanceof ValidationException) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'status' => 422,
|
||||
'message' => $e->getMessage(),
|
||||
'errors' => $e->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
if ($e instanceof AuthenticationException) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'status' => 401,
|
||||
'message' => 'Bạn chưa đăng nhập hoặc phiên đăng nhập đã hết hạn.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
if ($e instanceof QueryException) {
|
||||
if (($e->errorInfo[1] ?? null) == 1062) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Dữ liệu đã tồn tại'
|
||||
'error' => true,
|
||||
'status' => 422,
|
||||
'message' => 'Dữ liệu đã tồn tại.',
|
||||
], 422);
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'status' => 500,
|
||||
'message' => 'Lỗi cơ sở dữ liệu.',
|
||||
], 500);
|
||||
}
|
||||
|
||||
$this->renderable(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e, $request) {
|
||||
if (!$request->expectsJson() && !$request->is('v1/*') && !$request->is('api/*')) {
|
||||
return null;
|
||||
}
|
||||
if ($e instanceof HttpException) {
|
||||
$status = $e->getStatusCode();
|
||||
$messages = [
|
||||
401 => 'Bạn chưa đăng nhập.',
|
||||
402 => 'Thanh toán bắt buộc.',
|
||||
403 => 'Bạn không có quyền thực hiện hành động này.',
|
||||
404 => 'Không tìm thấy tài nguyên.',
|
||||
405 => 'Phương thức không được phép.',
|
||||
419 => 'Phiên làm việc đã hết hạn, vui lòng thử lại.',
|
||||
422 => 'Dữ liệu không hợp lệ.',
|
||||
429 => 'Quá nhiều yêu cầu, vui lòng thử lại sau.',
|
||||
500 => 'Lỗi máy chủ nội bộ.',
|
||||
502 => 'Cổng kết nối không hợp lệ.',
|
||||
503 => 'Dịch vụ tạm thời không khả dụng.',
|
||||
];
|
||||
|
||||
$previous = $e->getPrevious();
|
||||
|
||||
if ($previous instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
|
||||
$modelClass = $previous->getModel();
|
||||
$pageType = match ($modelClass) {
|
||||
\App\Models\Product::class => 'service',
|
||||
$pageType = match ($modelClass) {
|
||||
\App\Models\Product::class => 'service',
|
||||
\App\Models\Customer::class => 'client',
|
||||
\App\Models\Post::class => 'post',
|
||||
default => 'unknown',
|
||||
\App\Models\Post::class => 'post',
|
||||
default => 'unknown',
|
||||
};
|
||||
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Dữ liệu không tồn tại',
|
||||
'error' => true,
|
||||
'status' => 404,
|
||||
'message' => 'Dữ liệu không tồn tại.',
|
||||
'page_type' => $pageType,
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'API Route not found',
|
||||
], 404);
|
||||
});
|
||||
'error' => true,
|
||||
'status' => $status,
|
||||
'message' => $e->getMessage() ?: ($messages[$status] ?? 'Đã xảy ra lỗi.'),
|
||||
], $status);
|
||||
}
|
||||
|
||||
$status = method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500;
|
||||
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'status' => $status,
|
||||
'message' => config('app.debug') ? $e->getMessage() : 'Đã xảy ra lỗi máy chủ.',
|
||||
], $status);
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ class VerifyCsrfToken extends Middleware
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
'/administrator/ckfinder/*'
|
||||
'/administrator/ckfinder/*',
|
||||
'api/*',
|
||||
'v1/*',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -38,15 +38,15 @@ class RouteServiceProvider extends ServiceProvider
|
||||
$this->configureRateLimiting();
|
||||
|
||||
$this->routes(function () {
|
||||
Route::middleware(['api', 'json.response'])
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/client.php'));
|
||||
|
||||
Route::prefix('api')
|
||||
->middleware(['api', 'json.response'])
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api.php'));
|
||||
|
||||
Route::middleware(['api', 'json.response'])
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/client.php'));
|
||||
|
||||
Route::middleware('web')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/admin.php'));
|
||||
|
||||
+3
-9
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
@@ -15,20 +14,15 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => ['api/*', 'sanctum/csrf-cookie', 'v1/*'],
|
||||
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
'allowed_origins' => ['*', 'http://localhost:5173/', 'http://localhost:3000/', 'http://localhost:3001/', 'https://127.0.0.1/'],
|
||||
'allowed_origins' => ['*'],
|
||||
|
||||
'allowed_origins_patterns' => [],
|
||||
|
||||
'allowed_headers' => ['*'],
|
||||
|
||||
'exposed_headers' => [],
|
||||
|
||||
'max_age' => 0,
|
||||
|
||||
'supports_credentials' => false,
|
||||
|
||||
'supports_credentials' => true,
|
||||
];
|
||||
|
||||
+2
-1
@@ -175,8 +175,9 @@ Route::any('{any}', function () {
|
||||
return response()->json(
|
||||
[
|
||||
'error' => true,
|
||||
'status' => 404,
|
||||
'message' => 'API Route not found',
|
||||
],
|
||||
404,
|
||||
);
|
||||
})->where('any', '.*');
|
||||
})->where('any', '^v1/.*');
|
||||
|
||||
Reference in New Issue
Block a user