Logs, Categories created
This commit is contained in:
parent
823d498de7
commit
8ca7fa0fd0
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Resources\UserResource;
|
||||
use App\Mail\EmailActivation;
|
||||
use App\Models\Log;
|
||||
use App\Models\Token;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
@ -59,6 +60,8 @@ class AuthController extends Controller
|
||||
|
||||
$user = User::create($fields);
|
||||
|
||||
Log::writeLog("User '" . $user->username . "' is registered");
|
||||
|
||||
$token = Token::existsToken($user, 'email_verification');
|
||||
if(!$token) {
|
||||
$token = Token::createToken($user, 'email_verification');
|
||||
@ -126,6 +129,8 @@ class AuthController extends Controller
|
||||
}
|
||||
$token = $user->createToken('auth_token')->plainTextToken;
|
||||
|
||||
Log::writeLog("User '" . $user->username . "' is logged into his account");
|
||||
|
||||
return response()->json([
|
||||
'access_token' => $token,
|
||||
'token_type' => 'Bearer',
|
||||
@ -297,6 +302,8 @@ class AuthController extends Controller
|
||||
$user->password = $new_password;
|
||||
$user->save();
|
||||
|
||||
Log::writeLog("User '" . $user->username . "' is resetted his password");
|
||||
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Your password was successfully changed!'
|
||||
|
||||
@ -2,62 +2,185 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreCategoryRequest;
|
||||
use App\Http\Requests\UpdateCategoryRequest;
|
||||
use App\Http\Resources\CategoryResource;
|
||||
use App\Models\Category;
|
||||
use App\Models\Log;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @OA\Get(
|
||||
* path="/api/categories",
|
||||
* summary="Get all categories",
|
||||
* tags={"Categories"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="List of categories",
|
||||
* @OA\JsonContent(
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/CategoryResource")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return Category::all();
|
||||
return CategoryResource::collection(Category::all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @OA\Post(
|
||||
* path="/api/categories",
|
||||
* summary="Create a new category (only admin)",
|
||||
* tags={"Categories"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* required={"name"},
|
||||
* @OA\Property(property="name", type="string", example="Physics")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Category created successfully",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CategoryResource")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=403,
|
||||
* description="Forbidden"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', Category::class);
|
||||
$fields = $request->validate([
|
||||
'name' => 'required|max:150'
|
||||
]);
|
||||
$category = Category::create($fields);
|
||||
|
||||
return $category;
|
||||
Log::writeLog("Category '" . $category->name . "' is created");
|
||||
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
* @OA\Get(
|
||||
* path="/api/categories/{id}",
|
||||
* summary="Get a specific category",
|
||||
* tags={"Categories"},
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* description="ID of the category",
|
||||
* @OA\Schema(type="integer", example=1)
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Category retrieved successfully",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CategoryResource")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="Category not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function show(Category $category)
|
||||
{
|
||||
return $category;
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @OA\Put(
|
||||
* path="/api/categories/{id}",
|
||||
* summary="Update a category (only admin)",
|
||||
* tags={"Categories"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* description="ID of the category",
|
||||
* @OA\Schema(type="integer", example=1)
|
||||
* ),
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* required={"name"},
|
||||
* @OA\Property(property="name", type="string", example="Physics Updated")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Category updated successfully",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CategoryResource")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=403,
|
||||
* description="Forbidden"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="Category not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function update(Request $request, Category $category)
|
||||
{
|
||||
$this->authorize('update', $category);
|
||||
$fields = $request->validate([
|
||||
'name' => 'required|max:150'
|
||||
]);
|
||||
$old_category_name = $category->name;
|
||||
$category->update($fields);
|
||||
|
||||
return $category;
|
||||
Log::writeLog("Category '$old_category_name' is renamed to '" . $category->name ."'");
|
||||
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @OA\Delete(
|
||||
* path="/api/categories/{id}",
|
||||
* summary="Delete a category (only admin)",
|
||||
* tags={"Categories"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* description="ID of the category",
|
||||
* @OA\Schema(type="integer", example=1)
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Category deleted successfully",
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(property="message", type="string", example="The category was deleted")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=403,
|
||||
* description="Forbidden"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="Category not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function destroy(Category $category)
|
||||
{
|
||||
$this->authorize('delete', $category);
|
||||
$category->delete();
|
||||
|
||||
Log::writeLog("Category '" . $category->name . "' is deleted");
|
||||
|
||||
return ['message' => 'The category was deleted'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
|
||||
/**
|
||||
* @OA\Info(
|
||||
* title="HoshiAI API",
|
||||
@ -11,5 +15,5 @@ namespace App\Http\Controllers;
|
||||
*/
|
||||
abstract class Controller
|
||||
{
|
||||
//
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
}
|
||||
|
||||
114
app/Http/Controllers/LogController.php
Normal file
114
app/Http/Controllers/LogController.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Resources\LogResource;
|
||||
use App\Models\Log;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
|
||||
class LogController extends Controller
|
||||
{
|
||||
private const PAGINATED_COUNT = 20;
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/logs",
|
||||
* summary="Get all logs (paginated, only admin)",
|
||||
* tags={"Logs"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="List of logs",
|
||||
* @OA\JsonContent(
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/LogResource")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=403,
|
||||
* description="Forbidden"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('viewAny', Log::class);
|
||||
return LogResource::collection(Log::paginate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/logs/{id}",
|
||||
* summary="Get a specific log (only admin)",
|
||||
* tags={"Logs"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* description="ID of the log",
|
||||
* @OA\Schema(type="integer", example=1)
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Log retrieved successfully",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LogResource")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=403,
|
||||
* description="Forbidden"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="Log not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function show(Log $log)
|
||||
{
|
||||
$this->authorize('view', $log);
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Delete(
|
||||
* path="/api/logs/{id}",
|
||||
* summary="Delete a specific log (only admin)",
|
||||
* tags={"Logs"},
|
||||
* security={{"bearerAuth": {}}},
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* description="ID of the log",
|
||||
* @OA\Schema(type="integer", example=1)
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Log deleted successfully",
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(property="message", type="string", example="This log is successfully deleted")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=403,
|
||||
* description="Forbidden"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="Log not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function destroy(Log $log)
|
||||
{
|
||||
$this->authorize('delete', $log);
|
||||
|
||||
$log->delete();
|
||||
return response()->json([
|
||||
'message' => 'This log is successfully deleted'
|
||||
]);
|
||||
}
|
||||
}
|
||||
54
app/Http/Resources/CategoryResource.php
Normal file
54
app/Http/Resources/CategoryResource.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="CategoryResource",
|
||||
* type="object",
|
||||
* title="Category",
|
||||
* description="Category resource with dynamic count",
|
||||
* @OA\Property(
|
||||
* property="id",
|
||||
* type="integer",
|
||||
* example=1
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="name",
|
||||
* type="string",
|
||||
* example="Books"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="created_at",
|
||||
* type="string",
|
||||
* format="date-time",
|
||||
* example="2025-11-10T18:00:00Z"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="count",
|
||||
* type="integer",
|
||||
* example=5,
|
||||
* description="Dynamic count of related items"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class CategoryResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'created_at' => $this->created_at,
|
||||
'count' => $this->count ?? 0
|
||||
];
|
||||
}
|
||||
}
|
||||
47
app/Http/Resources/LogResource.php
Normal file
47
app/Http/Resources/LogResource.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="LogResource",
|
||||
* type="object",
|
||||
* title="Log",
|
||||
* description="Log resource",
|
||||
* @OA\Property(
|
||||
* property="id",
|
||||
* type="integer",
|
||||
* example=1
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="description",
|
||||
* type="string",
|
||||
* example="User logged in"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="created_at",
|
||||
* type="string",
|
||||
* format="date-time",
|
||||
* example="2025-11-10T17:45:00.000000Z"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class LogResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'description' => $this->description,
|
||||
'created_at' => $this->created_at
|
||||
];
|
||||
}
|
||||
}
|
||||
40
app/Models/Log.php
Normal file
40
app/Models/Log.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Log extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'description',
|
||||
'type'
|
||||
];
|
||||
|
||||
/**
|
||||
* Creating new log
|
||||
* @param string $descpr
|
||||
* @return void
|
||||
*/
|
||||
public static function writeLog(string $descpr, string $type = 'access')
|
||||
{
|
||||
self::create(['description' => $descpr, 'type' => $type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'created_at' => 'datetime'
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -8,22 +8,6 @@ use Illuminate\Auth\Access\Response;
|
||||
|
||||
class CategoryPolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Category $category): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
@ -47,20 +31,4 @@ class CategoryPolicy
|
||||
{
|
||||
return $user->type === 'admin';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the model.
|
||||
*/
|
||||
public function restore(User $user, Category $category): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the model.
|
||||
*/
|
||||
public function forceDelete(User $user, Category $category): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
34
app/Policies/LogPolicy.php
Normal file
34
app/Policies/LogPolicy.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Log;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
|
||||
class LogPolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->type === 'admin';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Log $log): bool
|
||||
{
|
||||
return $user->type === 'admin';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Log $log): bool
|
||||
{
|
||||
return $user->type === 'admin';
|
||||
}
|
||||
}
|
||||
@ -40,6 +40,11 @@ return [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
|
||||
'sanctum' => [
|
||||
'driver' => 'sanctum',
|
||||
'provider' => 'users',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@ -171,10 +171,10 @@ return [
|
||||
'securityDefinitions' => [
|
||||
'securitySchemes' => [
|
||||
'bearerAuth' => [
|
||||
'type' => 'http',
|
||||
'scheme' => 'bearer',
|
||||
'bearerFormat' => 'JWT'
|
||||
],
|
||||
'type' => 'http',
|
||||
'scheme' => 'bearer',
|
||||
'bearerFormat' => 'JWT'
|
||||
],
|
||||
/*
|
||||
* Examples of Security schemes
|
||||
*/
|
||||
|
||||
29
database/migrations/2025_11_10_200607_create_logs_table.php
Normal file
29
database/migrations/2025_11_10_200607_create_logs_table.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string("description", 255);
|
||||
$table->enum('type', ['error', 'access'])->default('access');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('logs');
|
||||
}
|
||||
};
|
||||
@ -2,14 +2,24 @@
|
||||
|
||||
use App\Http\Controllers\AuthController;
|
||||
use App\Http\Controllers\CategoryController;
|
||||
use App\Http\Controllers\LogController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
// Route::get('/user', function (Request $request) {
|
||||
// return $request->user();
|
||||
// })->middleware('auth:sanctum');
|
||||
|
||||
Route::apiResource('categories', CategoryController::class);
|
||||
|
||||
// CategoryController
|
||||
Route::get('categories', [CategoryController::class, 'index']);
|
||||
Route::get('categories/{category}', [CategoryController::class, 'show']);
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::post('categories', [CategoryController::class, 'store']);
|
||||
Route::put('categories/{category}', [CategoryController::class, 'update']);
|
||||
Route::delete('categories/{category}', [CategoryController::class, 'destroy']);
|
||||
});
|
||||
|
||||
Route::apiResource('logs', LogController::class)
|
||||
->only(['index', 'show', 'destroy'])->middleware('auth:sanctum');
|
||||
|
||||
// AuthController
|
||||
Route::post('/auth/register', [ AuthController::class, 'register' ]);
|
||||
@ -18,4 +28,8 @@ Route::post('/auth/logout', [ AuthController::class, 'logout' ])->middleware('au
|
||||
Route::post('/auth/forgot-password', [ AuthController::class, 'forgotPassword' ]);
|
||||
Route::post('/auth/reset-password', [ AuthController::class, 'resetPassword' ]);
|
||||
Route::post('/auth/activate-account', [ AuthController::class, 'confirmationAccount' ]);
|
||||
Route::get('/auth/me', [ AuthController::class, 'me' ])->middleware('auth:sanctum');
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::post('/auth/logout', [ AuthController::class, 'logout' ]);
|
||||
Route::get('/auth/me', [ AuthController::class, 'me' ])->middleware('auth:sanctum');
|
||||
});
|
||||
@ -546,10 +546,399 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/categories": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Categories"
|
||||
],
|
||||
"summary": "Get all categories",
|
||||
"operationId": "3f5817a34833d0a1f4af4548dd3aeaba",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of categories",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/CategoryResource"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"Categories"
|
||||
],
|
||||
"summary": "Create a new category (only admin)",
|
||||
"operationId": "71fcad552bb0eaba9fb191fd8d8dcab0",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Physics"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Category created successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CategoryResource"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/categories/{id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Categories"
|
||||
],
|
||||
"summary": "Get a specific category",
|
||||
"operationId": "c68e76d323c008827a9e47398b1583de",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of the category",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Category retrieved successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CategoryResource"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Category not found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"Categories"
|
||||
],
|
||||
"summary": "Update a category (only admin)",
|
||||
"operationId": "0e686b2748211cc688333ed705dc111f",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of the category",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Physics Updated"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Category updated successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CategoryResource"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"description": "Category not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"Categories"
|
||||
],
|
||||
"summary": "Delete a category (only admin)",
|
||||
"operationId": "4c12e22a7f8c617bd83bfa1fdc05428d",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of the category",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Category deleted successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "The category was deleted"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"description": "Category not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/logs": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Logs"
|
||||
],
|
||||
"summary": "Get all logs (paginated, only admin)",
|
||||
"operationId": "07258c00ce1b2cbc7c7151a7cc8ca986",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of logs",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/LogResource"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/logs/{id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Logs"
|
||||
],
|
||||
"summary": "Get a specific log (only admin)",
|
||||
"operationId": "caa09131dde473dca25ea025d181146a",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of the log",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Log retrieved successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/LogResource"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"description": "Log not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"Logs"
|
||||
],
|
||||
"summary": "Delete a specific log (only admin)",
|
||||
"operationId": "2a0e57b9168eaca7e207f5b35f469666",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of the log",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Log deleted successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "This log is successfully deleted"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"description": "Log not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"CategoryResource": {
|
||||
"title": "Category",
|
||||
"description": "Category resource with dynamic count",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Books"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"example": "2025-11-10T18:00:00Z"
|
||||
},
|
||||
"count": {
|
||||
"description": "Dynamic count of related items",
|
||||
"type": "integer",
|
||||
"example": 5
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"LogResource": {
|
||||
"title": "Log",
|
||||
"description": "Log resource",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "User logged in"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"example": "2025-11-10T17:45:00.000000Z"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"UserResource": {
|
||||
"properties": {
|
||||
"id": {
|
||||
@ -596,6 +985,14 @@
|
||||
{
|
||||
"name": "Auth",
|
||||
"description": "Auth"
|
||||
},
|
||||
{
|
||||
"name": "Categories",
|
||||
"description": "Categories"
|
||||
},
|
||||
{
|
||||
"name": "Logs",
|
||||
"description": "Logs"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user