2984 lines
119 KiB
JSON
2984 lines
119 KiB
JSON
{
|
|
"openapi": "3.0.0",
|
|
"info": {
|
|
"title": "HoshiAI API",
|
|
"description": "Documentaion for project",
|
|
"version": "1.0.0"
|
|
},
|
|
"paths": {
|
|
"/api/auth/register": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Register a new user",
|
|
"operationId": "d764dd091cc4494ae0baf360b03319f3",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"username",
|
|
"email",
|
|
"password",
|
|
"password_confirmation"
|
|
],
|
|
"properties": {
|
|
"username": {
|
|
"type": "string",
|
|
"maxLength": 100,
|
|
"example": "root"
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"format": "email",
|
|
"maxLength": 100,
|
|
"example": "root@example.com"
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "123456"
|
|
},
|
|
"password_confirmation": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "123456"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "User registered successfully. Confirmation email sent.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "You successfully registered! Please, confirm your account using email"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"email": [
|
|
"The email has already been taken."
|
|
],
|
|
"password": [
|
|
"The password must be at least 6 characters."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/login": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "User login",
|
|
"operationId": "8dcb70df1020986038d098cc08d05dae",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"email",
|
|
"password"
|
|
],
|
|
"properties": {
|
|
"email": {
|
|
"type": "string",
|
|
"format": "email",
|
|
"example": "root@example.com"
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "123456"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Login successful",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"access_token": {
|
|
"type": "string",
|
|
"example": "1|JfjOc5DkOHHTtWnM4SdpLM0BR0YvpycoeNAWanlH1305fab7"
|
|
},
|
|
"token_type": {
|
|
"type": "string",
|
|
"example": "Bearer"
|
|
},
|
|
"user": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Invalid credentials",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Invalid credentials"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Email not verified",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Please verify your email first"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/logout": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Logout current user",
|
|
"operationId": "69281b12abb272c76871f19cb17ca563",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Successfully logged out",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Successfully logged out"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Unauthenticated"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/auth/forgot-password": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Send password reset link to user email",
|
|
"operationId": "cff9b52a898f73f39d684747bd69c4e1",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"email"
|
|
],
|
|
"properties": {
|
|
"email": {
|
|
"type": "string",
|
|
"format": "email",
|
|
"example": "user@example.com"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Password reset link sent successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Password reset link has been sent to your email. Please check your inbox."
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "User not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "User is not found"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"email": [
|
|
"The email must be a valid email address."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/reset-password": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Reset user password using token",
|
|
"operationId": "6af92e090f994419a2295111b391a205",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"token",
|
|
"password",
|
|
"password_confirmation"
|
|
],
|
|
"properties": {
|
|
"token": {
|
|
"type": "string",
|
|
"example": "abcdef123456"
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "newpassword123"
|
|
},
|
|
"password_confirmation": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "newpassword123"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Password reset successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Your password was successfully changed!"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Invalid token",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Your token is not valid"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"password": [
|
|
"The password must be at least 6 characters."
|
|
],
|
|
"password_confirmation": [
|
|
"The password confirmation does not match."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/confirmation-account": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Confirm user account via email verification token",
|
|
"operationId": "c8ecdf6fd50dc4c70fcc5bf19233e462",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"token"
|
|
],
|
|
"properties": {
|
|
"token": {
|
|
"type": "string",
|
|
"example": "abcdef123456"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Account successfully activated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Your account was successfully activated"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Invalid token",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Your token is not valid"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"token": [
|
|
"The token field is required."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/me": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Get current user info",
|
|
"operationId": "b9abb1a7a74670a19c215c2c133f14d8",
|
|
"responses": {
|
|
"200": {
|
|
"description": "User info",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"user": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/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/hitcounts": {
|
|
"get": {
|
|
"tags": [
|
|
"Hitcounts"
|
|
],
|
|
"summary": "Get list of hitcounts (paginated, only admin)",
|
|
"description": "Returns a paginated list of all recorded hitcounts. Requires admin privileges.",
|
|
"operationId": "getHitcounts",
|
|
"responses": {
|
|
"200": {
|
|
"description": "List of hitcounts",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"data": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/HitcountResource"
|
|
}
|
|
},
|
|
"links": {
|
|
"type": "object"
|
|
},
|
|
"meta": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden (not admin)"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/hitcounts/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Hitcounts"
|
|
],
|
|
"summary": "Get a specific hitcount (only admin)",
|
|
"description": "Returns detailed information about a specific hitcount. Requires admin privileges.",
|
|
"operationId": "getHitcount",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "Hitcount ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Hitcount details",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/HitcountResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden (not admin)"
|
|
},
|
|
"404": {
|
|
"description": "Not Found"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Hitcounts"
|
|
],
|
|
"summary": "Delete a hitcount (only admin)",
|
|
"description": "Deletes a specific hitcount entry. Requires admin privileges.",
|
|
"operationId": "deleteHitcount",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "Hitcount ID to delete",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Hitcount deleted successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The hitcount was deleted"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden (not admin)"
|
|
},
|
|
"404": {
|
|
"description": "Not Found"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/hit": {
|
|
"post": {
|
|
"tags": [
|
|
"Hitcounts"
|
|
],
|
|
"summary": "Register a hit for a URL",
|
|
"description": "Stores information about a visit, including IP, device, user agent, and country",
|
|
"operationId": "8297226e4c0d09764edb0821edbf282f",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"url"
|
|
],
|
|
"properties": {
|
|
"url": {
|
|
"type": "string",
|
|
"maxLength": 255,
|
|
"example": "https://my-application.com"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Hitcount successfully set",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The hitcount is set"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"url": [
|
|
"The url field is required."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/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": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/questions": {
|
|
"get": {
|
|
"tags": [
|
|
"Questions"
|
|
],
|
|
"summary": "Get a paginated list of questions (paginated)",
|
|
"description": "Retrieve questions. Optional filter by category_id.",
|
|
"operationId": "e64d3c7a745fc05662a4a1e1eb3d96ab",
|
|
"parameters": [
|
|
{
|
|
"name": "category_id",
|
|
"in": "query",
|
|
"description": "Filter questions by category ID",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"name": "page",
|
|
"in": "query",
|
|
"description": "Page number for pagination",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"default": 1
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Paginated list of questions",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"data": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/QuestionResource"
|
|
}
|
|
},
|
|
"links": {
|
|
"type": "object",
|
|
"example": {
|
|
"first": "http://localhost/api/questions?page=1",
|
|
"last": "http://localhost/api/questions?page=10",
|
|
"prev": null,
|
|
"next": "http://localhost/api/questions?page=2"
|
|
}
|
|
},
|
|
"meta": {
|
|
"type": "object",
|
|
"example": {
|
|
"current_page": 1,
|
|
"from": 1,
|
|
"last_page": 10,
|
|
"path": "http://localhost/api/questions",
|
|
"per_page": 15,
|
|
"to": 15,
|
|
"total": 150
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Questions"
|
|
],
|
|
"summary": "Create a new question (only admin or creator)",
|
|
"description": "Store a new question in the system.",
|
|
"operationId": "788d85763184ddf1b557afb040547f32",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"title",
|
|
"type",
|
|
"difficulty",
|
|
"variants",
|
|
"correct_answers"
|
|
],
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"maxLength": 255,
|
|
"example": "Sample question"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Optional description",
|
|
"nullable": true
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"single",
|
|
"multiply",
|
|
"text"
|
|
],
|
|
"example": "single"
|
|
},
|
|
"difficulty": {
|
|
"type": "integer",
|
|
"example": 2
|
|
},
|
|
"variants": {
|
|
"type": "array",
|
|
"items": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"example": "Option 1"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"correct_answers": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
},
|
|
"category_id": {
|
|
"type": "integer",
|
|
"example": 3,
|
|
"nullable": true
|
|
},
|
|
"is_pending_question": {
|
|
"type": "integer",
|
|
"example": 0
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Question created successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/QuestionResource"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/questions/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Questions"
|
|
],
|
|
"summary": "Get a single question",
|
|
"description": "Retrieve a single question by its ID, including author and category",
|
|
"operationId": "bea45702e58c27163e9dc928d8984dfa",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "ID of the question to retrieve",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Question retrieved successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/QuestionResource"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Questions"
|
|
],
|
|
"summary": "Update a question (only admin or creator)",
|
|
"description": "Update an existing question by ID.",
|
|
"operationId": "795b02e5ecdc23fd74f20e0671a40f8c",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "ID of the question to update",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"title",
|
|
"type",
|
|
"difficulty",
|
|
"variants",
|
|
"correct_answers"
|
|
],
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"maxLength": 255,
|
|
"example": "Updated question"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Updated description",
|
|
"nullable": true
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"single",
|
|
"multiply",
|
|
"text"
|
|
],
|
|
"example": "multiply"
|
|
},
|
|
"difficulty": {
|
|
"type": "integer",
|
|
"example": 3
|
|
},
|
|
"variants": {
|
|
"type": "array",
|
|
"items": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"example": "Option 1"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"correct_answers": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
},
|
|
"category_id": {
|
|
"type": "integer",
|
|
"example": 2,
|
|
"nullable": true
|
|
},
|
|
"is_pending_question": {
|
|
"type": "integer",
|
|
"example": 0
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Question updated successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/QuestionResource"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Questions"
|
|
],
|
|
"summary": "Delete a question (only admin or creator)",
|
|
"description": "Delete a question by ID .",
|
|
"operationId": "b2cbd34337a604c75c8a94f1a6e2f252",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "ID of the question to delete",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Question deleted successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The hitcount was deleted"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/tests": {
|
|
"get": {
|
|
"tags": [
|
|
"Tests"
|
|
],
|
|
"summary": "Get a list of tests (paginated)",
|
|
"description": "Retrieve a paginated list of tests. Optionally filter by category_id.",
|
|
"operationId": "5f539f69bb1d910182eb35136c5baa3a",
|
|
"parameters": [
|
|
{
|
|
"name": "category_id",
|
|
"in": "query",
|
|
"description": "Filter tests by category ID",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Paginated list of tests",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"data": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/TestResource"
|
|
}
|
|
},
|
|
"links": {
|
|
"properties": {
|
|
"first": {
|
|
"type": "string",
|
|
"example": "http://api.example.com/tests?page=1"
|
|
},
|
|
"last": {
|
|
"type": "string",
|
|
"example": "http://api.example.com/tests?page=10"
|
|
},
|
|
"prev": {
|
|
"type": "string",
|
|
"example": null,
|
|
"nullable": true
|
|
},
|
|
"next": {
|
|
"type": "string",
|
|
"example": "http://api.example.com/tests?page=2",
|
|
"nullable": true
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"meta": {
|
|
"properties": {
|
|
"current_page": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"from": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"last_page": {
|
|
"type": "integer",
|
|
"example": 10
|
|
},
|
|
"path": {
|
|
"type": "string",
|
|
"example": "http://api.example.com/tests"
|
|
},
|
|
"per_page": {
|
|
"type": "integer",
|
|
"example": 15
|
|
},
|
|
"to": {
|
|
"type": "integer",
|
|
"example": 15
|
|
},
|
|
"total": {
|
|
"type": "integer",
|
|
"example": 150
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Tests"
|
|
],
|
|
"summary": "Create a new test (only admin or creator)",
|
|
"description": "Store a new test in the system (only admin or creator).",
|
|
"operationId": "7728a2f3dd87105d6d617df9a3f231d4",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"title",
|
|
"closed_at",
|
|
"questions"
|
|
],
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"maxLength": 255,
|
|
"example": "Sample Test"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Optional description",
|
|
"nullable": true
|
|
},
|
|
"closed_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-12-01 23:59:59",
|
|
"nullable": true
|
|
},
|
|
"category_id": {
|
|
"type": "integer",
|
|
"example": 3,
|
|
"nullable": true
|
|
},
|
|
"questions": {
|
|
"description": "Array of question IDs to attach to this test",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Test created successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TestResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/tests/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Tests"
|
|
],
|
|
"summary": "Get a single test",
|
|
"description": "Retrieve a single test with its questions, category, and author",
|
|
"operationId": "7e3d8428f4df82c6d4ee7bd1d4d2128c",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "Test ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Test retrieved successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TestResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Test not found"
|
|
}
|
|
}
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Tests"
|
|
],
|
|
"summary": "Update a test (only admin or creator)",
|
|
"description": "Update a test's data and associated questions (only admin/creator).",
|
|
"operationId": "ca1490751234c723e0a4a708afe16dd6",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "Test ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"title",
|
|
"questions"
|
|
],
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"maxLength": 255,
|
|
"example": "Updated Test Title"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Optional description",
|
|
"nullable": true
|
|
},
|
|
"category_id": {
|
|
"type": "integer",
|
|
"example": 3,
|
|
"nullable": true
|
|
},
|
|
"closed_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-12-01T23:59:59Z",
|
|
"nullable": true
|
|
},
|
|
"questions": {
|
|
"description": "Array of question IDs to attach to this test",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Test updated successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TestResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Tests"
|
|
],
|
|
"summary": "Delete a test (only admin or creator)",
|
|
"description": "Delete a test by ID (only admin or creator).",
|
|
"operationId": "92f76a68796679554c71a4659f62b296",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "Test ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Test deleted successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The test was deleted"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"description": "Test not found"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/users": {
|
|
"get": {
|
|
"tags": [
|
|
"Users"
|
|
],
|
|
"summary": "Get list of users (paginated, only admin)",
|
|
"operationId": "c457726701591d1183b53aa71fc13441",
|
|
"responses": {
|
|
"200": {
|
|
"description": "List of users retrieved successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"data": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
}
|
|
},
|
|
"links": {
|
|
"type": "object"
|
|
},
|
|
"meta": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden — user is not authorized to view users"
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Users"
|
|
],
|
|
"summary": "Create a new user (only admin)",
|
|
"operationId": "592819a0265360b2014512d6dbfaf0e7",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"username",
|
|
"email",
|
|
"password",
|
|
"type"
|
|
],
|
|
"properties": {
|
|
"username": {
|
|
"type": "string",
|
|
"maxLength": 100,
|
|
"example": "newuser"
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"format": "email",
|
|
"maxLength": 100,
|
|
"example": "newuser@example.com"
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "secret123"
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"admin",
|
|
"user"
|
|
],
|
|
"example": "user"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "User created successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"email": [
|
|
"The email has already been taken."
|
|
],
|
|
"password": [
|
|
"The password must be at least 6 characters."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden — only admins can create users"
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/users/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Users"
|
|
],
|
|
"summary": "Get a specific user (only admin)",
|
|
"operationId": "36a33ff774d5cba33c039dec2c3e0287",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "User ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "User retrieved successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "User not found"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden — user not authorized to view this resource"
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Users"
|
|
],
|
|
"summary": "Update an existing user (only admin)",
|
|
"operationId": "b9091397c8b25f12c6adb74be6ce3a5a",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "User ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"username",
|
|
"email",
|
|
"password",
|
|
"type"
|
|
],
|
|
"properties": {
|
|
"username": {
|
|
"type": "string",
|
|
"maxLength": 100,
|
|
"example": "updated_user"
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"format": "email",
|
|
"maxLength": 100,
|
|
"example": "updated_user@example.com"
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"format": "password",
|
|
"example": "newpassword123"
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"admin",
|
|
"user"
|
|
],
|
|
"example": "user"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "User updated successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "User not found"
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The given data was invalid."
|
|
},
|
|
"errors": {
|
|
"type": "object",
|
|
"example": {
|
|
"email": [
|
|
"The email has already been taken."
|
|
],
|
|
"password": [
|
|
"The password must be at least 6 characters."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden — only admins can update users"
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Users"
|
|
],
|
|
"summary": "Delete a user (only admin)",
|
|
"operationId": "fa56cffde745d3f152f95cbacd936c0b",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "User ID",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"204": {
|
|
"description": "User deleted successfully (no content)"
|
|
},
|
|
"404": {
|
|
"description": "User not found"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden — only admins can delete users"
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/user-tests": {
|
|
"get": {
|
|
"tags": [
|
|
"UserTests"
|
|
],
|
|
"summary": "Get list of user tests for the authenticated user",
|
|
"description": "Retrieve all UserTests belonging to the authenticated user, with related category, test, and answers.",
|
|
"operationId": "bf312e7c74799e8dbaa29025b8f52f46",
|
|
"responses": {
|
|
"200": {
|
|
"description": "List of user tests",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"data": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/UserTestResource"
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"UserTests"
|
|
],
|
|
"summary": "Create a new user test",
|
|
"description": "Generate a new UserTest for the authenticated user with questions from a specific category and difficulty range.",
|
|
"operationId": "dab4526b31f8a1bf1abf3048c3a4ecbe",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"category_id"
|
|
],
|
|
"properties": {
|
|
"category_id": {
|
|
"description": "Category from which to select questions",
|
|
"type": "integer",
|
|
"example": 3
|
|
},
|
|
"min_difficulty": {
|
|
"description": "Minimum difficulty of questions",
|
|
"type": "integer",
|
|
"example": 0,
|
|
"nullable": true
|
|
},
|
|
"max_difficulty": {
|
|
"description": "Maximum difficulty of questions",
|
|
"type": "integer",
|
|
"example": 10,
|
|
"nullable": true
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"422": {
|
|
"description": "Validation error or no questions found"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/user-tests/by-test": {
|
|
"post": {
|
|
"tags": [
|
|
"UserTests"
|
|
],
|
|
"summary": "Create a UserTest based on an existing Test",
|
|
"description": "Generates a UserTest from an existing Test, including all its questions. Only available if the Test is available.",
|
|
"operationId": "81b613bf7df7621756ee71dc88027236",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"test_id"
|
|
],
|
|
"properties": {
|
|
"test_id": {
|
|
"description": "ID of the existing Test to create a UserTest from",
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "UserTest created successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserTestResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Test is not available at this time"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/user-test-answers/{answer}/submit": {
|
|
"post": {
|
|
"tags": [
|
|
"UserTestAnswers"
|
|
],
|
|
"summary": "Submit an answer for a UserTestAnswer",
|
|
"description": "Records the user's answer for a specific UserTestAnswer. The answer must match the question type (string for text, integer for single/multiple choice).",
|
|
"operationId": "4a7d5822bbbe5fe72fed7aca775ab792",
|
|
"parameters": [
|
|
{
|
|
"name": "answer",
|
|
"in": "path",
|
|
"description": "ID of the UserTestAnswer to submit",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"required": [
|
|
"answer"
|
|
],
|
|
"properties": {
|
|
"answer": {
|
|
"description": "Array of answers. Should be string(s) if the question type is 'text' or integer(s) otherwise",
|
|
"type": "array",
|
|
"items": {
|
|
"oneOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "integer"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Answer recorded successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Answer is recorded"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"description": "Validation error (wrong type or empty array)"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden (user cannot edit this answer)"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/user-test-answers/{answer}": {
|
|
"get": {
|
|
"tags": [
|
|
"UserTestAnswers"
|
|
],
|
|
"summary": "Get a UserTestAnswer",
|
|
"description": "Retrieve a specific UserTestAnswer by ID. Only the owner or authorized user can view it.",
|
|
"operationId": "ea81ce3e7c5383b8fabeef5338bb1db9",
|
|
"parameters": [
|
|
{
|
|
"name": "answer",
|
|
"in": "path",
|
|
"description": "ID of the UserTestAnswer to retrieve",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "UserTestAnswer retrieved successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserTestAnswerResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden: user cannot view this answer"
|
|
},
|
|
"404": {
|
|
"description": "UserTestAnswer not found"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/user-tests/{userTest}/complete": {
|
|
"post": {
|
|
"tags": [
|
|
"UserTests"
|
|
],
|
|
"summary": "Complete a UserTest",
|
|
"description": "Marks a UserTest as completed, calculates the score based on answers, and prevents further editing.",
|
|
"operationId": "d9265537e9cfb510ba68eede4930ea09",
|
|
"parameters": [
|
|
{
|
|
"name": "userTest",
|
|
"in": "path",
|
|
"description": "ID of the UserTest to complete",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Test successfully completed",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "Test is completed"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden: user cannot edit this test"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/user-tests/{userTest}": {
|
|
"get": {
|
|
"tags": [
|
|
"UserTests"
|
|
],
|
|
"summary": "Get a single UserTest",
|
|
"description": "Retrieve a UserTest with its answers, question details, category, and user info.",
|
|
"operationId": "0de523e8221fc7a1b13fb6dbfd40e3f3",
|
|
"parameters": [
|
|
{
|
|
"name": "userTest",
|
|
"in": "path",
|
|
"description": "ID of the UserTest to retrieve",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "UserTest details",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserTestResource"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden: user cannot view this test"
|
|
},
|
|
"404": {
|
|
"description": "UserTest not found"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"UserTests"
|
|
],
|
|
"summary": "Delete a UserTest",
|
|
"description": "Delete a UserTest by ID. Only the owner or admin can delete it.",
|
|
"operationId": "a5e4b2f9860f4428f72bd99b5eb9688d",
|
|
"parameters": [
|
|
{
|
|
"name": "userTest",
|
|
"in": "path",
|
|
"description": "ID of the UserTest to delete",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "UserTest deleted successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "The UserTest was deleted"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden: user cannot delete this test"
|
|
},
|
|
"404": {
|
|
"description": "UserTest 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"
|
|
},
|
|
"HitcountResource": {
|
|
"title": "Hitcount",
|
|
"description": "Hitcount resource",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"ip": {
|
|
"type": "string",
|
|
"example": "127.0.0.1"
|
|
},
|
|
"device_type": {
|
|
"type": "string",
|
|
"example": "desktop"
|
|
},
|
|
"user_agent": {
|
|
"type": "string",
|
|
"example": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0"
|
|
},
|
|
"country": {
|
|
"type": "string",
|
|
"example": "Japan"
|
|
},
|
|
"url": {
|
|
"type": "string",
|
|
"example": "https://my-application.com"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-10T17:45:00.000000Z"
|
|
}
|
|
},
|
|
"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"
|
|
},
|
|
"QuestionResource": {
|
|
"title": "Question",
|
|
"description": "Question resource",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"title": {
|
|
"type": "string",
|
|
"example": "What is the capital of Japan?"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Choose the correct option",
|
|
"nullable": true
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"single",
|
|
"multiply",
|
|
"text"
|
|
],
|
|
"example": "single"
|
|
},
|
|
"difficulty": {
|
|
"type": "integer",
|
|
"example": 3
|
|
},
|
|
"variants": {
|
|
"type": "array",
|
|
"items": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"example": "Tokyo"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"nullable": true
|
|
},
|
|
"correct_answers": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"example": 1
|
|
}
|
|
},
|
|
"category_id": {
|
|
"type": "integer",
|
|
"example": 3,
|
|
"nullable": true
|
|
},
|
|
"category": {
|
|
"$ref": "#/components/schemas/CategoryResource"
|
|
},
|
|
"author_id": {
|
|
"type": "integer",
|
|
"example": 2,
|
|
"nullable": true
|
|
},
|
|
"author": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T10:00:00.000000Z"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T10:05:00.000000Z"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"TestResource": {
|
|
"title": "Test",
|
|
"description": "Test resource",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"title": {
|
|
"type": "string",
|
|
"example": "Sample Test"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Optional description",
|
|
"nullable": true
|
|
},
|
|
"category_id": {
|
|
"type": "integer",
|
|
"example": 3,
|
|
"nullable": true
|
|
},
|
|
"category": {
|
|
"$ref": "#/components/schemas/CategoryResource"
|
|
},
|
|
"questions": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/QuestionResource"
|
|
}
|
|
},
|
|
"author_id": {
|
|
"type": "integer",
|
|
"example": 2,
|
|
"nullable": true
|
|
},
|
|
"author": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
},
|
|
"closed_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T10:30:00Z",
|
|
"nullable": true
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T10:00:00Z"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T10:15:00Z"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"UserResource": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"example": "root"
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"example": "root@example.com"
|
|
},
|
|
"email_verified_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"example": "user"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"UserTestAnswerResource": {
|
|
"title": "UserTestAnswer",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"user_test_id": {
|
|
"type": "integer",
|
|
"example": 5
|
|
},
|
|
"question_id": {
|
|
"type": "integer",
|
|
"example": 12
|
|
},
|
|
"question": {
|
|
"$ref": "#/components/schemas/QuestionResource"
|
|
},
|
|
"answer": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"example": [
|
|
"42",
|
|
"43"
|
|
]
|
|
},
|
|
"user_id": {
|
|
"type": "integer",
|
|
"example": 10
|
|
},
|
|
"user": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
},
|
|
"is_correct": {
|
|
"type": "boolean",
|
|
"example": true
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T20:39:22Z"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T20:39:22Z"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"UserTestResource": {
|
|
"title": "UserTest",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"example": 1
|
|
},
|
|
"test_id": {
|
|
"type": "integer",
|
|
"example": 5
|
|
},
|
|
"test": {
|
|
"$ref": "#/components/schemas/TestResource"
|
|
},
|
|
"user_id": {
|
|
"type": "integer",
|
|
"example": 10
|
|
},
|
|
"user": {
|
|
"$ref": "#/components/schemas/UserResource"
|
|
},
|
|
"closed_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-12-01T23:59:59Z"
|
|
},
|
|
"is_completed": {
|
|
"type": "boolean",
|
|
"example": false
|
|
},
|
|
"score": {
|
|
"type": "integer",
|
|
"example": 85
|
|
},
|
|
"is_available": {
|
|
"type": "boolean",
|
|
"example": true
|
|
},
|
|
"answers": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/UserTestAnswerResource"
|
|
}
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T20:39:22Z"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"example": "2025-11-11T20:39:22Z"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"securitySchemes": {
|
|
"bearerAuth": {
|
|
"type": "http",
|
|
"scheme": "bearer",
|
|
"bearerFormat": "JWT"
|
|
}
|
|
}
|
|
},
|
|
"tags": [
|
|
{
|
|
"name": "Auth",
|
|
"description": "Auth"
|
|
},
|
|
{
|
|
"name": "Categories",
|
|
"description": "Categories"
|
|
},
|
|
{
|
|
"name": "Hitcounts",
|
|
"description": "Hitcounts"
|
|
},
|
|
{
|
|
"name": "Logs",
|
|
"description": "Logs"
|
|
},
|
|
{
|
|
"name": "Questions",
|
|
"description": "Questions"
|
|
},
|
|
{
|
|
"name": "Tests",
|
|
"description": "Tests"
|
|
},
|
|
{
|
|
"name": "Users",
|
|
"description": "Users"
|
|
},
|
|
{
|
|
"name": "UserTests",
|
|
"description": "UserTests"
|
|
},
|
|
{
|
|
"name": "UserTestAnswers",
|
|
"description": "UserTestAnswers"
|
|
}
|
|
]
|
|
} |