mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-20 16:23:30 +00:00
feat(api): add tag management endpoints for applications, databases, and services
Add CRUD tag endpoints (GET/POST/DELETE) as sub-resources for applications, databases, and services. Add team-level GET /tags endpoint. Extend all resource creation endpoints to accept an optional tags array. Uses a shared HandlesTagsApi trait to avoid duplication across controllers. Tags are race-safe via syncWithoutDetaching(), garbage-collected when orphaned, and sanitized (strip_tags + lowercase).
This commit is contained in:
@@ -27,6 +27,18 @@ use OpenApi\Attributes as OA;
|
||||
|
||||
class DatabasesController extends Controller
|
||||
{
|
||||
use Concerns\HandlesTagsApi;
|
||||
|
||||
protected function findTaggableResource(string $uuid, int|string $teamId): mixed
|
||||
{
|
||||
return queryDatabaseByUuidWithinTeam($uuid, $teamId);
|
||||
}
|
||||
|
||||
protected function tagResourceNotFoundMessage(): string
|
||||
{
|
||||
return 'Database not found.';
|
||||
}
|
||||
|
||||
private function removeSensitiveData($database)
|
||||
{
|
||||
$database->makeHidden([
|
||||
@@ -1079,6 +1091,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1147,6 +1160,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1214,6 +1228,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1282,6 +1297,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1350,6 +1366,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1421,6 +1438,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1492,6 +1510,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1560,6 +1579,7 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'],
|
||||
'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'],
|
||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'],
|
||||
'tags' => ['type' => 'array', 'items' => new OA\Items(type: 'string'), 'description' => 'Tags to assign to the database.'],
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1689,6 +1709,8 @@ class DatabasesController extends Controller
|
||||
'limits_cpuset' => 'string|nullable',
|
||||
'limits_cpu_shares' => 'numeric',
|
||||
'instant_deploy' => 'boolean',
|
||||
'tags' => 'array|nullable',
|
||||
'tags.*' => 'string|min:2',
|
||||
]);
|
||||
if ($validator->failed()) {
|
||||
return response()->json([
|
||||
@@ -1707,7 +1729,7 @@ class DatabasesController extends Controller
|
||||
}
|
||||
}
|
||||
if ($type === NewDatabaseTypes::POSTGRESQL) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'postgres_user' => 'string',
|
||||
'postgres_password' => 'string',
|
||||
@@ -1752,6 +1774,9 @@ class DatabasesController extends Controller
|
||||
$request->offsetSet('postgres_conf', $postgresConf);
|
||||
}
|
||||
$database = create_standalone_postgresql($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -1766,7 +1791,7 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(serializeApiResponse($payload))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::MARIADB) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'clickhouse_admin_user' => 'string',
|
||||
'clickhouse_admin_password' => 'string',
|
||||
@@ -1807,6 +1832,9 @@ class DatabasesController extends Controller
|
||||
$request->offsetSet('mariadb_conf', $mariadbConf);
|
||||
}
|
||||
$database = create_standalone_mariadb($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -1822,7 +1850,7 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(serializeApiResponse($payload))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::MYSQL) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mysql_root_password', 'mysql_password', 'mysql_user', 'mysql_database', 'mysql_conf'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mysql_root_password', 'mysql_password', 'mysql_user', 'mysql_database', 'mysql_conf', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'mysql_root_password' => 'string',
|
||||
'mysql_password' => 'string',
|
||||
@@ -1866,6 +1894,9 @@ class DatabasesController extends Controller
|
||||
$request->offsetSet('mysql_conf', $mysqlConf);
|
||||
}
|
||||
$database = create_standalone_mysql($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -1881,7 +1912,7 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(serializeApiResponse($payload))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::REDIS) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'redis_password', 'redis_conf'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'redis_password', 'redis_conf', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'redis_password' => 'string',
|
||||
'redis_conf' => 'string',
|
||||
@@ -1922,6 +1953,9 @@ class DatabasesController extends Controller
|
||||
$request->offsetSet('redis_conf', $redisConf);
|
||||
}
|
||||
$database = create_standalone_redis($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -1937,7 +1971,7 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(serializeApiResponse($payload))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::DRAGONFLY) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'dragonfly_password'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'dragonfly_password', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'dragonfly_password' => 'string',
|
||||
]);
|
||||
@@ -1959,6 +1993,9 @@ class DatabasesController extends Controller
|
||||
|
||||
removeUnnecessaryFieldsFromRequest($request);
|
||||
$database = create_standalone_dragonfly($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -1967,7 +2004,7 @@ class DatabasesController extends Controller
|
||||
'uuid' => $database->uuid,
|
||||
]))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::KEYDB) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'keydb_password', 'keydb_conf'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'keydb_password', 'keydb_conf', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'keydb_password' => 'string',
|
||||
'keydb_conf' => 'string',
|
||||
@@ -2008,6 +2045,9 @@ class DatabasesController extends Controller
|
||||
$request->offsetSet('keydb_conf', $keydbConf);
|
||||
}
|
||||
$database = create_standalone_keydb($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -2023,7 +2063,7 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(serializeApiResponse($payload))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::CLICKHOUSE) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'clickhouse_admin_user', 'clickhouse_admin_password'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'clickhouse_admin_user', 'clickhouse_admin_password', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'clickhouse_admin_user' => 'string',
|
||||
'clickhouse_admin_password' => 'string',
|
||||
@@ -2044,6 +2084,9 @@ class DatabasesController extends Controller
|
||||
}
|
||||
removeUnnecessaryFieldsFromRequest($request);
|
||||
$database = create_standalone_clickhouse($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -2059,7 +2102,7 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(serializeApiResponse($payload))->setStatusCode(201);
|
||||
} elseif ($type === NewDatabaseTypes::MONGODB) {
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_database'];
|
||||
$allowedFields = ['name', 'description', 'image', 'public_port', 'public_port_timeout', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_database', 'tags'];
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'mongo_conf' => 'string',
|
||||
'mongo_initdb_root_username' => 'string',
|
||||
@@ -2102,6 +2145,9 @@ class DatabasesController extends Controller
|
||||
$request->offsetSet('mongo_conf', $mongoConf);
|
||||
}
|
||||
$database = create_standalone_mongodb($environment->id, $destination->uuid, $request->all());
|
||||
if ($request->has('tags')) {
|
||||
$this->attachTagsToResource($database, $request->tags, $teamId);
|
||||
}
|
||||
if ($instantDeploy) {
|
||||
StartDatabase::dispatch($database);
|
||||
}
|
||||
@@ -3856,4 +3902,148 @@ class DatabasesController extends Controller
|
||||
|
||||
return response()->json(['message' => 'Storage deleted.']);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
summary: 'List Tags',
|
||||
description: 'List tags for a database by UUID.',
|
||||
path: '/databases/{uuid}/tags',
|
||||
operationId: 'list-tags-by-database-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Databases'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the database.',
|
||||
required: true,
|
||||
schema: new OA\Schema(type: 'string')
|
||||
),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'List of tags.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'array',
|
||||
items: new OA\Items(ref: '#/components/schemas/Tag')
|
||||
)
|
||||
),
|
||||
]
|
||||
),
|
||||
new OA\Response(response: 401, ref: '#/components/responses/401'),
|
||||
new OA\Response(response: 400, ref: '#/components/responses/400'),
|
||||
new OA\Response(response: 404, ref: '#/components/responses/404'),
|
||||
]
|
||||
)]
|
||||
public function tags(Request $request): JsonResponse
|
||||
{
|
||||
return $this->listTags($request);
|
||||
}
|
||||
|
||||
#[OA\Post(
|
||||
summary: 'Create Tag',
|
||||
description: 'Add tag(s) to a database by UUID.',
|
||||
path: '/databases/{uuid}/tags',
|
||||
operationId: 'create-tag-by-database-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Databases'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the database.',
|
||||
required: true,
|
||||
schema: new OA\Schema(type: 'string')
|
||||
),
|
||||
],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'tag_name' => ['type' => 'string', 'description' => 'The tag name (min 2 characters). Required if tag_names is not provided.'],
|
||||
'tag_names' => [
|
||||
'type' => 'array',
|
||||
'items' => new OA\Items(type: 'string'),
|
||||
'description' => 'Array of tag names (each min 2 characters). Required if tag_name is not provided.',
|
||||
],
|
||||
],
|
||||
)
|
||||
),
|
||||
]
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 201,
|
||||
description: 'Tags added successfully.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'array',
|
||||
items: new OA\Items(ref: '#/components/schemas/Tag')
|
||||
)
|
||||
),
|
||||
]
|
||||
),
|
||||
new OA\Response(response: 401, ref: '#/components/responses/401'),
|
||||
new OA\Response(response: 400, ref: '#/components/responses/400'),
|
||||
new OA\Response(response: 404, ref: '#/components/responses/404'),
|
||||
new OA\Response(response: 422, ref: '#/components/responses/422'),
|
||||
]
|
||||
)]
|
||||
public function create_tag(Request $request): JsonResponse
|
||||
{
|
||||
return $this->createTag($request);
|
||||
}
|
||||
|
||||
#[OA\Delete(
|
||||
summary: 'Delete Tag',
|
||||
description: 'Remove a tag from a database by UUID.',
|
||||
path: '/databases/{uuid}/tags/{tag_uuid}',
|
||||
operationId: 'delete-tag-by-database-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Databases'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the database.',
|
||||
required: true,
|
||||
schema: new OA\Schema(type: 'string')
|
||||
),
|
||||
new OA\Parameter(
|
||||
name: 'tag_uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the tag.',
|
||||
required: true,
|
||||
schema: new OA\Schema(type: 'string')
|
||||
),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Tag removed.',
|
||||
),
|
||||
new OA\Response(response: 401, ref: '#/components/responses/401'),
|
||||
new OA\Response(response: 400, ref: '#/components/responses/400'),
|
||||
new OA\Response(response: 404, ref: '#/components/responses/404'),
|
||||
]
|
||||
)]
|
||||
public function delete_tag(Request $request): JsonResponse
|
||||
{
|
||||
return $this->deleteTag($request);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user