From 36886454582a1d5ec9a46a57bfe220338209cd02 Mon Sep 17 00:00:00 2001 From: amikhaylov Date: Wed, 27 May 2026 12:20:50 +0300 Subject: [PATCH] Updated README --- README.md | 16 +- app/Http/Controllers/CategoryController.php | 22 ++ gigs_api_collection.json | 242 ++++++++++++++++++++ routes/api.php | 19 +- 4 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 app/Http/Controllers/CategoryController.php create mode 100644 gigs_api_collection.json diff --git a/README.md b/README.md index 498c951..42c370d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## 🛠 Стек технологий - **PHP:** 8.2 / 8.3 -- **Framework:** Laravel 11.x (или ваша версия) +- **Framework:** Laravel 12.x - **Database:** MySQL / PostgreSQL - **API Specification:** Postman (коллекция в корне проекта) @@ -74,12 +74,21 @@ "password": "your_password" } ``` + +#### 4. Выход из системы (Logout) +* **URL:** `/api/logout` +* **Метод:** `POST` +* **Описание:** Деактивирует и удаляет текущий API-токен Sanctum, с которым был выполнен запрос. Заговоловок Authorization c токеном обязателен. + +--- + *В ответе возвращаются данные пользователя и его `access_token` для авторизации в защищенных эндпоинтах.* ### 2. Получение списка событий с фильтрацией и пагинацией * **URL:** `/api/gigs` * **Метод:** `GET` +* **Описание:** для метода необходим заголовок Authorization: Bearer {{token}}, который можно получить методом /login. #### Параметры запроса (Query Parameters): @@ -95,3 +104,8 @@ --- +## 🧪 Тестирование в Postman + +В корне репозитория находится файл коллекции для быстрого тестирования всех эндпоинтов: **`gigs_api_collection.json`**. + + diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php new file mode 100644 index 0000000..877f08a --- /dev/null +++ b/app/Http/Controllers/CategoryController.php @@ -0,0 +1,22 @@ +get(); + + return response()->json([ + 'status' => 'success', + 'message' => 'Categories retrieved successfully', + 'data' => $categories + ], 200); + } +} diff --git a/gigs_api_collection.json b/gigs_api_collection.json new file mode 100644 index 0000000..9c539d4 --- /dev/null +++ b/gigs_api_collection.json @@ -0,0 +1,242 @@ +{ + "info": { + "_postman_id": "2e44665b-610d-4022-9d35-c5d4ba3182cc", + "name": "Gigs API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "55246252", + "_collection_link": "https://blacksnowman-7b5016ee-929558.postman.co/workspace/RoadCrew's-Workspace~f1936404-0a84-43c8-873a-5676fefcbc04/collection/55246252-2e44665b-610d-4022-9d35-c5d4ba3182cc?action=share&source=collection_link&creator=55246252" + }, + "item": [ + { + "name": "Get basic user", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + }, + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{server}}/api/user", + "host": [ + "{{server}}" + ], + "path": [ + "api", + "user" + ] + } + }, + "response": [] + }, + { + "name": "Get gigs", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + }, + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{server}}/api/gigs?categories[]=1&categories[]=4&date_from=2026-02-01&date_to=2026-05-31", + "host": [ + "{{server}}" + ], + "path": [ + "api", + "gigs" + ], + "query": [ + { + "key": "categories[]", + "value": "1" + }, + { + "key": "categories[]", + "value": "4" + }, + { + "key": "date_from", + "value": "2026-02-01" + }, + { + "key": "date_to", + "value": "2026-05-31" + } + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// 1. Проверяем, что сервер вернул успешный HTTP-статус (200 OK)", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "// 2. Парсим JSON-ответ и сохраняем токен", + "if (pm.response.code === 200) {", + " const responseJson = pm.response.json();", + " ", + " // Проверяем, что в ответе есть статус 'success' и сам токен", + " if (responseJson.status === \"success\" && responseJson.data && responseJson.data.access_token) {", + " const token = responseJson.data.access_token;", + " ", + " // Сохраняем токен в ГЛОБАЛЬНУЮ переменную", + " pm.globals.set(\"token\", token);", + " ", + " console.log(\"Токен успешно сохранен в глобальную переменную 'token':\", token);", + " } else {", + " console.error(\"Не удалось найти 'access_token' в ответе сервера\");", + " }", + "}" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{ \n \"email\": \"test@example.com\",\n \"password\": \"123456\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{server}}/api/login", + "host": [ + "{{server}}" + ], + "path": [ + "api", + "login" + ] + } + }, + "response": [] + }, + { + "name": "Loout", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// 1. Проверяем, что сервер вернул успешный HTTP-статус (200 OK)", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "// 2. Парсим JSON-ответ и сохраняем токен", + "if (pm.response.code === 200) {", + " const responseJson = pm.response.json();", + " ", + " // Проверяем, что в ответе есть статус 'success' и сам токен", + " if (responseJson.status === \"success\" && responseJson.data && responseJson.data.access_token) {", + " const token = responseJson.data.access_token;", + " ", + " // Сохраняем токен в ГЛОБАЛЬНУЮ переменную", + " pm.globals.set(\"token\", token);", + " ", + " console.log(\"Токен успешно сохранен в глобальную переменную 'token':\", token);", + " } else {", + " console.error(\"Не удалось найти 'access_token' в ответе сервера\");", + " }", + "}" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + }, + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "url": { + "raw": "{{server}}/api/logout", + "host": [ + "{{server}}" + ], + "path": [ + "api", + "logout" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 849c2aa..a1a4623 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,22 +1,27 @@ group(function () { - Route::post('/logout', [ LoginController::class, 'logout' ]); -}); - Route::get('/user', function (Request $request) { return $request->user(); })->middleware('auth:sanctum'); +Route::middleware('auth:sanctum')->group(function () { + // Получение списка категорий + Route::get('/categories', [ CategoryController::class, 'index' ]); -Route::get('/gigs', [ GigsController::class, 'index' ]) - ->middleware('auth:sanctum'); + // Получение списка событий (с фильтрами и пагинацией) + Route::get('/gigs', [ GigsController::class, 'index' ]); + + // Выход из системы (отзыв токена) + Route::post('/logout', [ LoginController::class, 'logout' ]); +});