new api 2.0

This commit is contained in:
daniel 2024-01-23 17:02:23 +01:00
parent 89b1d3317e
commit a11ebc6a57
53 changed files with 3083 additions and 61 deletions

View File

@ -3,7 +3,9 @@
use Slim\App;
return function (App $app) {
(include __DIR__.'/../../../include/lib/Modules/Users/routes.php')($app);
(include __DIR__.'/../../../include/lib/Modules/Profiles/routes.php')($app);
(include __DIR__.'/../../../include/lib/Modules/Events/routes.php')($app);
(include __DIR__.'/../../../include/lib/Modules/Groups/routes.php')($app);
(include __DIR__.'/../../../include/lib/Modules/Profiles/routes.php')($app);
(include __DIR__.'/../../../include/lib/Modules/Tags/routes.php')($app);
(include __DIR__.'/../../../include/lib/Modules/Users/routes.php')($app);
};

View File

@ -1,8 +1,8 @@
{
"openapi": "3.0.0",
"info": {
"title": "Nueva API de Pandora FMS",
"description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Libero, quibusdam esse commodi rem nisi cumque quos ut, exercitationem recusandae ipsam fuga qui veritatis non temporibus perferendis earum amet cupiditate eum nam corrupti! Dicta tempora, debitis molestiae corrupti sequi asperiores libero perferendis ut aperiam laboriosam repudiandae neque, rem quidem consectetur. Magnam illum perferendis aspernatur quibusdam esse? Libero eius veritatis quae perspiciatis. Sit recusandae aspernatur possimus autem! Corporis ipsa voluptatem placeat quasi praesentium esse doloremque magni, error, cumque vel, consequatur quam saepe iusto accusantium tempore ab dignissimos alias sint officia fuga voluptas. Vel repudiandae dicta ipsum repellat reprehenderit. Molestiae, ullam dolorum voluptatem necessitatibus itaque officiis ducimus consectetur aut facilis atque aliquid reiciendis voluptas sit incidunt, repellendus soluta quod obcaecati unde quas. Error officiis cumque vero minima amet modi enim, placeat consectetur cupiditate, fugiat odit sunt a earum natus dicta, labore id dolor! Quis laboriosam a quasi fuga! Ullam consectetur, voluptates repellat eveniet delectus officia nostrum amet obcaecati adipisci natus voluptas explicabo dolores similique doloribus. Rerum voluptatibus aperiam quidem necessitatibus, sint dignissimos natus delectus dolorem dicta sunt eum doloribus eligendi similique a at in repellat fuga voluptatem atque consectetur, ratione sit! Magni tenetur quos laborum, excepturi eveniet laboriosam optio aperiam eaque sit iusto.",
"title": "API Pandora FMS",
"description": "Documentacion para desarrolladores de la nueva api de pandora fms.",
"termsOfService": "https://example.com/terms/",
"contact": {
"name": "Pandorafms",
@ -460,6 +460,218 @@
]
}
},
"/group": {
"post": {
"tags": ["Groups"],
"summary": "Creates a new groups",
"operationId": "2c799105ff37ce09e5aec019cd500615",
"requestBody": {
"$ref": "#/components/requestBodies/requestBodyGroup"
},
"responses": {
"200": {
"$ref": "#/components/responses/ResponseGroup"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/group/{idGroup}": {
"get": {
"tags": ["Groups"],
"summary": "Show group",
"operationId": "e617d2dd05b5da29729a629b722e489e",
"parameters": [
{
"$ref": "#/components/parameters/parameterIdGroup"
}
],
"responses": {
"200": {
"$ref": "#/components/responses/ResponseGroup"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
},
"put": {
"tags": ["Groups"],
"summary": "Updates an group",
"operationId": "1b9f27089e1734250037a2542a63216e",
"parameters": [
{
"$ref": "#/components/parameters/parameterIdGroup"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/requestBodyGroup"
},
"responses": {
"200": {
"$ref": "#/components/responses/ResponseGroup"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
},
"delete": {
"tags": ["Groups"],
"summary": "Deletes an group object.",
"operationId": "d61a992170621de9cc9a2cb61f90de3f",
"parameters": [
{
"$ref": "#/components/parameters/parameterIdGroup"
}
],
"responses": {
"200": {
"$ref": "#/components/responses/successfullyDeleted"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/group/list": {
"post": {
"tags": ["Groups"],
"summary": "List groups",
"operationId": "3bbc68353ef79c71c178426336f21b93",
"parameters": [
{
"$ref": "#/components/parameters/parameterPage"
},
{
"$ref": "#/components/parameters/parameterSizePage"
},
{
"$ref": "#/components/parameters/parameterSortField"
},
{
"$ref": "#/components/parameters/parameterSortDirection"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/requestBodyGroupFilter"
},
"responses": {
"200": {
"description": "List Groups Object",
"content": {
"application/json": {
"schema": {
"properties": {
"paginationData": {
"$ref": "#/components/schemas/paginationData"
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Group"
}
}
},
"type": "object"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/profile": {
"post": {
"tags": ["Profiles"],
@ -672,6 +884,218 @@
]
}
},
"/tag": {
"post": {
"tags": ["Tags"],
"summary": "Creates a new tags",
"operationId": "c2511f535e2073c2e91f1d9c71a594a5",
"requestBody": {
"$ref": "#/components/requestBodies/requestBodyTag"
},
"responses": {
"200": {
"$ref": "#/components/responses/ResponseTag"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/tag/{idTag}": {
"get": {
"tags": ["Tags"],
"summary": "Show tag",
"operationId": "fe2e12539c1e64bf9962ae0c83c6a2ca",
"parameters": [
{
"$ref": "#/components/parameters/parameterIdTag"
}
],
"responses": {
"200": {
"$ref": "#/components/responses/ResponseTag"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
},
"put": {
"tags": ["Tags"],
"summary": "Updates an tag",
"operationId": "80bf6897a82194c8dc44eaf21b6edc73",
"parameters": [
{
"$ref": "#/components/parameters/parameterIdTag"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/requestBodyTag"
},
"responses": {
"200": {
"$ref": "#/components/responses/ResponseTag"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
},
"delete": {
"tags": ["Tags"],
"summary": "Deletes an tag object.",
"operationId": "9f4c209e4eb50cad9c3db451ddeb32e1",
"parameters": [
{
"$ref": "#/components/parameters/parameterIdTag"
}
],
"responses": {
"200": {
"$ref": "#/components/responses/successfullyDeleted"
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/tag/list": {
"post": {
"tags": ["Tags"],
"summary": "List tags",
"operationId": "86fbbb0adcd5db93622153640b12f246",
"parameters": [
{
"$ref": "#/components/parameters/parameterPage"
},
{
"$ref": "#/components/parameters/parameterSizePage"
},
{
"$ref": "#/components/parameters/parameterSortField"
},
{
"$ref": "#/components/parameters/parameterSortDirection"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/requestBodyTagFilter"
},
"responses": {
"200": {
"description": "List Incidence object",
"content": {
"application/json": {
"schema": {
"properties": {
"paginationData": {
"$ref": "#/components/schemas/paginationData"
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Tag"
}
}
},
"type": "object"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/user": {
"post": {
"tags": ["Users"],
@ -1351,6 +1775,113 @@
}
]
},
"Group": {
"properties": {
"idGroup": {
"description": "Id group",
"type": "integer",
"readOnly": true,
"nullable": false
},
"name": {
"description": "Name group",
"type": "string",
"default": null,
"nullable": true
},
"icon": {
"description": "Path icon, by default: without-group@groups.svg",
"type": "string",
"default": null,
"readOnly": true,
"nullable": true
},
"parent": {
"description": "Id Group parent",
"type": "integer",
"default": null,
"nullable": true
},
"isPropagate": {
"description": "Group propagate",
"type": "boolean",
"default": "false",
"nullable": false
},
"isAlertEnabled": {
"description": "Group is alert enabled",
"type": "boolean",
"default": "true",
"nullable": false
},
"customId": {
"description": "Custom id",
"type": "string",
"default": null,
"nullable": true
},
"idSkin": {
"description": "Id skin",
"type": "integer",
"default": null,
"nullable": true
},
"description": {
"description": "Description",
"type": "string",
"default": null,
"nullable": true
},
"contact": {
"description": "Contact",
"type": "string",
"default": null,
"nullable": true
},
"other": {
"description": "Other things",
"type": "string",
"default": null,
"nullable": true
},
"password": {
"type": "string",
"default": null,
"writeOnly": true,
"nullable": true
},
"maxAgents": {
"description": "Maximum number of agents per group",
"type": "integer",
"default": 0,
"nullable": false
}
},
"type": "object"
},
"GroupFilter": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Group"
},
{
"properties": {
"idGroup": {
"default": null,
"readOnly": false
},
"freeSearch": {
"description": "Find word in name field.",
"type": "string",
"default": null,
"nullable": true
}
},
"type": "object"
}
]
},
"Profile": {
"properties": {
"idProfile": {
@ -1565,6 +2096,72 @@
},
"type": "object"
},
"Tag": {
"properties": {
"idTag": {
"description": "Id Tag",
"type": "integer",
"readOnly": true,
"nullable": false
},
"name": {
"description": "Name of the tag",
"type": "string",
"default": null,
"nullable": false
},
"description": {
"description": "Description of the tag",
"type": "string",
"default": null,
"nullable": true
},
"url": {
"description": "Url of the tag",
"type": "string",
"default": null,
"nullable": true
},
"phone": {
"description": "Phone of the tag",
"type": "string",
"default": null,
"nullable": true
},
"previousName": {
"description": "Previous name of the tag",
"type": "string",
"default": null,
"readOnly": true,
"nullable": true,
"deprecated": true
}
},
"type": "object"
},
"TagFilter": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Tag"
},
{
"properties": {
"idTag": {
"default": null,
"readOnly": false
},
"freeSearch": {
"description": "Find word in name field.",
"type": "string",
"default": null,
"nullable": true
}
},
"type": "object"
}
]
},
"User": {
"properties": {
"idUser": {
@ -2066,6 +2663,16 @@
}
}
},
"ResponseGroup": {
"description": "Group object",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Group"
}
}
}
},
"ResponseProfile": {
"description": "Profile object",
"content": {
@ -2177,6 +2784,16 @@
}
}
},
"ResponseTag": {
"description": "Tag object",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Tag"
}
}
}
},
"ResponseUser": {
"description": "User object",
"content": {
@ -2219,6 +2836,16 @@
"default": 1
}
},
"parameterIdGroup": {
"name": "idGroup",
"in": "path",
"description": "Group id",
"required": true,
"schema": {
"type": "integer",
"default": 1
}
},
"parameterIdProfile": {
"name": "idProfile",
"in": "path",
@ -2270,6 +2897,16 @@
"enum": ["ascending", "descending"]
}
},
"parameterIdTag": {
"name": "idTag",
"in": "path",
"description": "Tag id",
"required": true,
"schema": {
"type": "integer",
"default": 1
}
},
"parameterIdUser": {
"name": "idUser",
"in": "path",
@ -2332,6 +2969,26 @@
}
}
},
"requestBodyGroup": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Group"
}
}
}
},
"requestBodyGroupFilter": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GroupFilter"
}
}
}
},
"requestBodyProfile": {
"required": true,
"content": {
@ -2352,6 +3009,26 @@
}
}
},
"requestBodyTag": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Tag"
}
}
}
},
"requestBodyTagFilter": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TagFilter"
}
}
}
},
"requestBodyUser": {
"required": true,
"content": {
@ -2405,30 +3082,24 @@
},
"tags": [
{
"name": "Users",
"description": "API Endpoints of users"
"name": "Events",
"description": "API Endpoints of events"
},
{
"name": "Groups",
"description": "API Endpoints of Groups"
},
{
"name": "Profiles",
"description": "API Endpoints of profiles"
},
{
"name": "Events",
"description": "API Endpoints of events"
}
],
"x-tagGroups": [
"name": "Tags",
"description": "API Endpoints of tags"
},
{
"name": "Users",
"tags": ["Users"]
},
{
"name": "Profiles",
"tags": ["Profiles"]
},
{
"name": "Events",
"tags": ["Events"]
"description": "API Endpoints of users"
}
]
}

View File

@ -2,8 +2,8 @@
namespace PandoraFMS\Modules\Events\Entities;
use PandoraFMS\Modules\Events\Validators\EventValidator;
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
use PandoraFMS\Modules\Shared\Validators\Validator;
/**
* @OA\Schema(
@ -74,13 +74,13 @@ final class EventFilter extends FilterAbstract
if($this->getEntityFilter() !== null) {
$validations = $this->getEntityFilter()->getValidations();
}
$validations['freeSearch'] = Validator::STRING;
$validations['freeSearch'] = EventValidator::STRING;
return $validations;
}
public function validateFields(array $filters): array
{
return (new Validator())->validate($filters);
return (new EventValidator())->validate($filters);
}
/**

View File

@ -6,6 +6,7 @@ use PandoraFMS\Core\Config;
use PandoraFMS\Modules\Events\Entities\Event;
use PandoraFMS\Modules\Events\Enums\EventSeverityEnum;
use PandoraFMS\Modules\Events\Enums\EventStatusEnum;
use PandoraFMS\Modules\Groups\Services\GetGroupService;
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
use PandoraFMS\Modules\Shared\Services\Timestamp;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
@ -17,7 +18,8 @@ final class EventValidation
private ValidateAclSystem $acl,
private Config $config,
private Timestamp $timestamp,
private GetUserService $getUserService
private GetUserService $getUserService,
private GetGroupService $getGroupService
) {
}
@ -107,10 +109,7 @@ final class EventValidation
protected function validateGroup(int $idGroup): void
{
// TODO: create new service for this.
if (! (bool) \groups_get_users($idGroup)) {
throw new BadRequestException(__('Invalid id group'));
}
$this->getGroupService->__invoke($idGroup);
}
protected function validateAgent(int $idAgent): void

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Groups\Actions;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Services\CreateGroupService;
final class CreateGroupAction
{
public function __construct(
private CreateGroupService $createGroupService
) {
}
public function __invoke(Group $group): Group
{
return $this->createGroupService->__invoke($group);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Groups\Actions;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Services\DeleteGroupService;
final class DeleteGroupAction
{
public function __construct(
private DeleteGroupService $deleteGroupService
) {
}
public function __invoke(Group $group): void
{
$this->deleteGroupService->__invoke($group);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Groups\Actions;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Services\GetGroupService;
final class GetGroupAction
{
public function __construct(
private GetGroupService $getGroupService
) {
}
public function __invoke(int $idGroup): Group
{
return $this->getGroupService->__invoke($idGroup);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace PandoraFMS\Modules\Groups\Actions;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Groups\Services\CountGroupService;
use PandoraFMS\Modules\Groups\Services\ListGroupService;
use PandoraFMS\Modules\Shared\Entities\PaginationData;
final class ListGroupAction
{
public function __construct(
private ListGroupService $listGroupService,
private CountGroupService $countGroupService
) {
}
public function __invoke(GroupFilter $groupFilter): array
{
return (new PaginationData(
$groupFilter->getPage(),
$groupFilter->getSizePage(),
$this->countGroupService->__invoke($groupFilter),
$this->listGroupService->__invoke($groupFilter)
))->toArray();
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Groups\Actions;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Services\UpdateGroupService;
final class UpdateGroupAction
{
public function __construct(
private UpdateGroupService $updateGroupService
) {
}
public function __invoke(Group $group, Group $oldGroup): Group
{
return $this->updateGroupService->__invoke($group, $oldGroup);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace PandoraFMS\Modules\Groups\Controllers;
use PandoraFMS\Modules\Groups\Actions\CreateGroupAction;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class CreateGroupController extends Controller
{
public function __construct(
private CreateGroupAction $createGroupAction,
private ValidateAclSystem $acl,
) {
}
/**
* @OA\Post(
* security={{ "bearerAuth": {}}},
* tags={"Groups"},
* path="/group",
* summary="Creates a new groups",
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyGroup"),
* @OA\Response(response=200, ref="#/components/responses/ResponseGroup"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
// @var Group $group.
$group = $this->fromRequest($request, Group::class);
$this->acl->validate(0, 'UM', ' tried to manage user');
$result = $this->createGroupAction->__invoke($group);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace PandoraFMS\Modules\Groups\Controllers;
use PandoraFMS\Modules\Groups\Actions\DeleteGroupAction;
use PandoraFMS\Modules\Groups\Actions\GetGroupAction;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class DeleteGroupController extends Controller
{
public function __construct(
private DeleteGroupAction $deleteGroupAction,
private ValidateAclSystem $acl,
private GetGroupAction $getGroupAction
) {
}
/**
* @OA\Delete(
* security={{ "bearerAuth": {}}},
* tags={"Groups"},
* path="/group/{idGroup}",
* summary="Deletes an group object.",
* @OA\Parameter(ref="#/components/parameters/parameterIdGroup"),
* @OA\Response(response=200, ref="#/components/responses/successfullyDeleted"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
$idGroup = $this->getParam($request, 'idGroup');
$group = $this->getGroupAction->__invoke($idGroup);
$this->acl->validate(0, 'UM', ' tried to manage user');
$result = $this->deleteGroupAction->__invoke($group);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace PandoraFMS\Modules\Groups\Controllers;
use PandoraFMS\Modules\Groups\Actions\GetGroupAction;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class GetGroupController extends Controller
{
public function __construct(
private GetGroupAction $getGroupAction,
private ValidateAclSystem $acl
) {
}
/**
* @OA\Get(
* security={{ "bearerAuth": {}}},
* path="/group/{idGroup}",
* tags={"Groups"},
* summary="Show group",
* @OA\Parameter(ref="#/components/parameters/parameterIdGroup"),
* @OA\Response(response=200, ref="#/components/responses/ResponseGroup"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
$idGroup = $this->getParam($request, 'idGroup');
$result = $this->getGroupAction->__invoke($idGroup);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace PandoraFMS\Modules\Groups\Controllers;
use PandoraFMS\Modules\Groups\Actions\ListGroupAction;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class ListGroupController extends Controller
{
public function __construct(
private ListGroupAction $listGroupAction,
private ValidateAclSystem $acl,
) {
}
/**
* @OA\Post(
* security={{ "bearerAuth": {}}},
* tags={"Groups"},
* path="/group/list",
* summary="List groups",
* @OA\Parameter(ref="#/components/parameters/parameterPage"),
* @OA\Parameter(ref="#/components/parameters/parameterSizePage"),
* @OA\Parameter(ref="#/components/parameters/parameterSortField"),
* @OA\Parameter(ref="#/components/parameters/parameterSortDirection"),
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyGroupFilter"),
* @OA\Response(
* response="200",
* description="List Groups Object",
* content={
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="paginationData",
* type="object",
* ref="#/components/schemas/paginationData",
* description="Page object",
* ),
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(
* ref="#/components/schemas/Group",
* description="Array of group objects"
* )
* ),
* ),
* )
* }
* ),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
// @var GroupFilter $groupFilter.
$groupFilter = $this->fromRequest($request, GroupFilter::class);
$result = $this->listGroupAction->__invoke($groupFilter);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace PandoraFMS\Modules\Groups\Controllers;
use PandoraFMS\Modules\Groups\Actions\GetGroupAction;
use PandoraFMS\Modules\Groups\Actions\UpdateGroupAction;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* @OA\Put(
* security={{ "bearerAuth": {}}},
* path="/group/{idGroup}",
* tags={"Groups"},
* summary="Updates an group",
* @OA\Parameter(ref="#/components/parameters/parameterIdGroup"),
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyGroup"),
* @OA\Response(response=200, ref="#/components/responses/ResponseGroup"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
final class UpdateGroupController extends Controller
{
public function __construct(
private UpdateGroupAction $updateGroupAction,
private ValidateAclSystem $acl,
private GetGroupAction $getGroupAction
) {
}
public function __invoke(Request $request, Response $response): Response
{
$idGroup = $this->getParam($request, 'idGroup');
$group = $this->getGroupAction->__invoke($idGroup);
$oldGroup = clone $group;
$params = $this->extractParams($request);
$group->fromArray($params);
$this->acl->validate(0, 'UM', ' tried to manage user');
$result = $this->updateGroupAction->__invoke($group, $oldGroup);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,349 @@
<?php
namespace PandoraFMS\Modules\Groups\Entities;
use PandoraFMS\Modules\Shared\Entities\Entity;
use PandoraFMS\Modules\Shared\Validators\Validator;
/**
* @OA\Schema(
* schema="Group",
* type="object",
* @OA\Property(
* property="idGroup",
* type="integer",
* nullable=false,
* description="Id group",
* readOnly=true
* ),
* @OA\Property(
* property="name",
* type="string",
* nullable=true,
* default=null,
* description="Name group",
* ),
* @OA\Property(
* property="icon",
* type="string",
* nullable=true,
* default=null,
* description="Path icon, by default: without-group@groups.svg",
* readOnly=true
* ),
* @OA\Property(
* property="parent",
* type="integer",
* nullable=true,
* default=null,
* description="Id Group parent",
* ),
* @OA\Property(
* property="isPropagate",
* type="boolean",
* nullable=false,
* default="false",
* description="Group propagate"
* ),
* @OA\Property(
* property="isAlertEnabled",
* type="boolean",
* nullable=false,
* default="true",
* description="Group is alert enabled"
* ),
* @OA\Property(
* property="customId",
* type="string",
* nullable=true,
* default=null,
* description="Custom id",
* ),
* @OA\Property(
* property="idSkin",
* type="integer",
* nullable=true,
* default=null,
* description="Id skin"
* ),
* @OA\Property(
* property="description",
* type="string",
* nullable=true,
* default=null,
* description="Description",
* ),
* @OA\Property(
* property="contact",
* type="string",
* nullable=true,
* default=null,
* description="Contact",
* ),
* @OA\Property(
* property="other",
* type="string",
* nullable=true,
* default=null,
* description="Other things",
* ),
* @OA\Property(
* property="password",
* type="string",
* nullable=true,
* default=null,
* writeOnly=true
* ),
* @OA\Property(
* property="maxAgents",
* type="integer",
* nullable=false,
* default=0,
* description="Maximum number of agents per group",
* )
* )
*
* @OA\Response(
* response="ResponseGroup",
* description="Group object",
* content={
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* ref="#/components/schemas/Group",
* description="Group object"
* ),
* )
* }
* )
*
* @OA\Parameter(
* parameter="parameterIdGroup",
* name="idGroup",
* in="path",
* description="Group id",
* required=true,
* @OA\Schema(
* type="integer",
* default=1
* )
* )
*
* @OA\RequestBody(
* request="requestBodyGroup",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/Group")
* )
* )
*/
final class Group extends Entity
{
private ?int $idGroup = null;
private ?string $name = null;
private ?string $icon = null;
private ?int $parent = null;
private ?bool $isPropagate = null;
private ?bool $isAlertEnabled = null;
private ?string $customId = null;
private ?int $idSkin = null;
private ?string $description = null;
private ?string $contact = null;
private ?string $other = null;
private ?string $password = null;
private ?int $maxAgents = null;
public function __construct()
{
}
public function fieldsReadOnly(): array
{
return ['idGroup' => 1];
}
public function jsonSerialize(): mixed
{
return [
'idGroup' => $this->getIdGroup(),
'name' => $this->getName(),
'icon' => $this->getIcon(),
'parent' => $this->getParent(),
'isPropagate' => $this->getIsPropagate(),
'isAlertEnabled' => $this->getIsAlertEnabled(),
'customId' => $this->getCustomId(),
'idSkin' => $this->getIdSkin(),
'description' => $this->getDescription(),
'contact' => $this->getContact(),
'other' => $this->getOther(),
'maxAgents' => $this->getMaxAgents(),
];
}
public function getValidations(): array
{
return [
'idGroup' => [
Validator::INTEGER,
Validator::GREATERTHAN,
],
'name' => Validator::STRING,
'icon' => Validator::STRING,
'parent' => [
Validator::INTEGER,
Validator::GREATEREQUALTHAN,
],
'isPropagate' => Validator::BOOLEAN,
'isAlertEnabled' => Validator::BOOLEAN,
'customId' => Validator::STRING,
'idSkin' => [
Validator::INTEGER,
Validator::GREATEREQUALTHAN,
],
'description' => Validator::STRING,
'contact' => Validator::STRING,
'other' => Validator::STRING,
'maxAgents' => [
Validator::INTEGER,
Validator::GREATEREQUALTHAN,
],
];
}
public function validateFields(array $filters): array
{
return (new Validator())->validate($filters);
}
public function getIdGroup(): ?int
{
return $this->idGroup;
}
public function setIdGroup(?int $idGroup): self
{
$this->idGroup = $idGroup;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getIcon(): ?string
{
return $this->icon;
}
public function setIcon(?string $icon): self
{
$this->icon = $icon;
return $this;
}
public function getParent(): ?int
{
return $this->parent;
}
public function setParent(?int $parent): self
{
$this->parent = $parent;
return $this;
}
public function getIsPropagate(): ?bool
{
return $this->isPropagate;
}
public function setIsPropagate(?bool $isPropagate): self
{
$this->isPropagate = $isPropagate;
return $this;
}
public function getIsAlertEnabled(): ?bool
{
return $this->isAlertEnabled;
}
public function setIsAlertEnabled(?bool $isAlertEnabled): self
{
$this->isAlertEnabled = $isAlertEnabled;
return $this;
}
public function getCustomId(): ?string
{
return $this->customId;
}
public function setCustomId(?string $customId): self
{
$this->customId = $customId;
return $this;
}
public function getIdSkin(): ?int
{
return $this->idSkin;
}
public function setIdSkin(?int $idSkin): self
{
$this->idSkin = $idSkin;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getContact(): ?string
{
return $this->contact;
}
public function setContact(?string $contact): self
{
$this->contact = $contact;
return $this;
}
public function getOther(): ?string
{
return $this->other;
}
public function setOther(?string $other): self
{
$this->other = $other;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(?string $password): self
{
$this->password = $password;
return $this;
}
public function getMaxAgents(): ?int
{
return $this->maxAgents;
}
public function setMaxAgents(?int $maxAgents): self
{
$this->maxAgents = $maxAgents;
return $this;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace PandoraFMS\Modules\Groups\Entities;
use PandoraFMS\Modules\Shared\Builders\Builder;
use PandoraFMS\Modules\Shared\Core\DataMapperAbstract;
use PandoraFMS\Modules\Shared\Core\MappeableInterface;
use PandoraFMS\Modules\Shared\Repositories\Repository;
final class GroupDataMapper extends DataMapperAbstract
{
public const TABLE_NAME = 'tgrupo';
public const ID_GROUP = 'id_grupo';
public const NAME = 'nombre';
public const ICON = 'icon';
public const PARENT = 'parent';
public const IS_PROPAGATE = 'propagate';
public const IS_DISABLED = 'disabled';
public const CUSTOM_ID = 'custom_id';
public const ID_SKIN = 'id_skin';
public const DESCRIPTION = 'description';
public const CONTACT = 'contact';
public const OTHER = 'other';
public const PASSWORD = 'password';
public const MAX_AGENTS = 'max_agents';
public function __construct(
private Repository $repository,
private Builder $builder,
) {
parent::__construct(
self::TABLE_NAME,
self::ID_GROUP,
);
}
public function getClassName(): string
{
return Group::class;
}
public function fromDatabase(array $data): Group
{
return $this->builder->build(new Group(), [
'idGroup' => $data[self::ID_GROUP],
'name' => $this->repository->safeOutput($data[self::NAME]),
'icon' => $data[self::ICON],
'parent' => $data[self::PARENT],
'isPropagate' => $data[self::IS_PROPAGATE],
'isAlertEnabled' => $data[self::IS_DISABLED],
'customId' => $data[self::CUSTOM_ID],
'idSkin' => $data[self::ID_SKIN],
'description' => $this->repository->safeOutput($data[self::DESCRIPTION]),
'contact' => $this->repository->safeOutput($data[self::CONTACT]),
'other' => $this->repository->safeOutput($data[self::OTHER]),
'password' => $data[self::PASSWORD],
'maxAgents' => $data[self::MAX_AGENTS],
]);
}
public function toDatabase(MappeableInterface $data): array
{
/** @var Group $data */
return [
self::ID_GROUP => $data->getIdGroup(),
self::NAME => $this->repository->safeInput($data->getName()),
self::ICON => $data->getIcon(),
self::PARENT => $data->getParent(),
self::IS_PROPAGATE => $data->getIsPropagate(),
self::IS_DISABLED => $data->getIsAlertEnabled(),
self::CUSTOM_ID => $data->getCustomId(),
self::ID_SKIN => $data->getIdSkin(),
self::DESCRIPTION => $this->repository->safeInput($data->getDescription()),
self::CONTACT => $this->repository->safeInput($data->getContact()),
self::OTHER => $this->repository->safeInput($data->getOther()),
self::PASSWORD => $this->repository->safeInput($data->getPassword()),
self::MAX_AGENTS => $data->getMaxAgents(),
];
}
}

View File

@ -0,0 +1,128 @@
<?php
namespace PandoraFMS\Modules\Groups\Entities;
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
use PandoraFMS\Modules\Shared\Validators\Validator;
/**
* @OA\Schema(
* schema="GroupFilter",
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/Group"),
* @OA\Schema(
* @OA\Property(
* property="idGroup",
* default=null,
* readOnly=false
* ),
* @OA\Property(
* property="freeSearch",
* type="string",
* nullable=true,
* default=null,
* description="Find word in name field."
* )
* )
* }
* )
*
* @OA\RequestBody(
* request="requestBodyGroupFilter",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/GroupFilter")
* ),
* )
*/
final class GroupFilter extends FilterAbstract
{
private ?string $freeSearch = null;
public function __construct()
{
$this->setDefaultFieldOrder(GroupDataMapper::NAME);
$this->setDefaultDirectionOrder($this::ASC);
$this->setEntityFilter(new Group());
}
public function fieldsTranslate(): array
{
return [
'idGroup' => GroupDataMapper::ID_GROUP,
'name' => GroupDataMapper::NAME,
'icon' => GroupDataMapper::ICON,
'parent' => GroupDataMapper::PARENT,
'isPropagate' => GroupDataMapper::IS_PROPAGATE,
'isAlertEnabled' => GroupDataMapper::IS_DISABLED,
'customId' => GroupDataMapper::CUSTOM_ID,
'idSkin' => GroupDataMapper::ID_SKIN,
'description' => GroupDataMapper::DESCRIPTION,
'contact' => GroupDataMapper::CONTACT,
'other' => GroupDataMapper::OTHER,
'password' => GroupDataMapper::PASSWORD,
'maxAgents' => GroupDataMapper::MAX_AGENTS,
];
}
public function fieldsReadOnly(): array
{
return ['password' => 1];
}
public function jsonSerialize(): mixed
{
return [
'freeSearch' => $this->getFreeSearch(),
];
}
public function getValidations(): array
{
$validations = [];
if($this->getEntityFilter() !== null) {
$validations = $this->getEntityFilter()->getValidations();
}
$validations['freeSearch'] = Validator::STRING;
return $validations;
}
public function validateFields(array $filters): array
{
return (new Validator())->validate($filters);
}
/**
* Get the value of freeSearch.
*
* @return ?string
*/
public function getFreeSearch(): ?string
{
return $this->freeSearch;
}
/**
* Set the value of freeSearch.
*
* @param ?string $freeSearch
*
*/
public function setFreeSearch(?string $freeSearch): self
{
$this->freeSearch = $freeSearch;
return $this;
}
/**
* Get the value of fieldsFreeSearch.
*
* @return ?array
*/
public function getFieldsFreeSearch(): ?array
{
return [GroupDataMapper::NAME, GroupDataMapper::DESCRIPTION];
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace PandoraFMS\Modules\Groups\Repositories;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Entities\GroupDataMapper;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Shared\Repositories\Repository;
class GroupRepository
{
public function __construct(
private Repository $repository,
private GroupDataMapper $groupDataMapper
) {
}
/**
* @return Group[],
*/
public function list(GroupFilter $groupFilter): array
{
return $this->repository->__list(
$groupFilter,
$this->groupDataMapper
);
}
public function count(GroupFilter $groupFilter): int
{
return $this->repository->__count(
$groupFilter,
$this->groupDataMapper
);
}
public function getOne(GroupFilter $groupFilter): Group
{
return $this->repository->__getOne(
$groupFilter,
$this->groupDataMapper
);
}
public function create(Group $group): Group
{
$id = $this->repository->__create($group, $this->groupDataMapper);
return $group->setIdGroup($id);
}
public function update(Group $group): Group
{
return $this->repository->__update(
$group,
$this->groupDataMapper,
$group->getIdGroup()
);
}
public function delete(int $id): void
{
$this->repository->__delete($id, $this->groupDataMapper);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
final class CountGroupService
{
public function __construct(
private GroupRepository $groupRepository,
) {
}
public function __invoke(GroupFilter $groupFilter): int
{
return $this->groupRepository->count($groupFilter);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
use PandoraFMS\Modules\Groups\Validations\GroupValidation;
use PandoraFMS\Modules\Shared\Services\Audit;
final class CreateGroupService
{
public function __construct(
private Audit $audit,
private GroupRepository $groupRepository,
private GroupValidation $groupValidation
) {
}
public function __invoke(Group $group): Group
{
$this->groupValidation->__invoke($group);
$group = $this->groupRepository->create($group);
$this->audit->write(
AUDIT_LOG_USER_MANAGEMENT,
'Create group '.$group->getIdGroup(),
json_encode($group->toArray())
);
return $group;
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
use PandoraFMS\Modules\Shared\Services\Audit;
final class DeleteGroupService
{
public function __construct(
private Audit $audit,
private GroupRepository $groupRepository,
) {
}
public function __invoke(Group $group): void
{
$idGroup = $group->getIdGroup();
// TODO: XXX
db_process_sql_update(
'tgrupo',
['parent' => $group->getParent()],
['parent' => $idGroup]
);
// TODO: XXX
db_process_sql_delete(
'tgroup_stat',
['id_group' => $idGroup]
);
$this->groupRepository->delete($idGroup);
$this->audit->write(
AUDIT_LOG_USER_MANAGEMENT,
'Deleted group '.$idGroup
);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
use PandoraFMS\Modules\Shared\Exceptions\NotFoundException;
final class ExistNameGroupService
{
public function __construct(
private GroupRepository $GroupRepository,
) {
}
public function __invoke(string $name): bool
{
$GroupFilter = new GroupFilter();
/** @var Group $entityFilter */
$entityFilter = $GroupFilter->getEntityFilter();
$entityFilter->setName($name);
try {
$this->GroupRepository->getOne($GroupFilter);
return true;
} catch (NotFoundException) {
return false;
}
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
final class GetGroupService
{
public function __construct(
private GroupRepository $groupRepository,
) {
}
public function __invoke(int $idGroup): Group
{
$groupFilter = new GroupFilter();
/** @var Group $entityFilter */
$entityFilter = $groupFilter->getEntityFilter();
$entityFilter->setIdGroup($idGroup);
return $this->groupRepository->getOne($groupFilter);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\GroupFilter;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
final class ListGroupService
{
public function __construct(
private GroupRepository $groupRepository,
) {
}
public function __invoke(GroupFilter $groupFilter): array
{
return $this->groupRepository->list($groupFilter);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace PandoraFMS\Modules\Groups\Services;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Repositories\GroupRepository;
use PandoraFMS\Modules\Groups\Validations\GroupValidation;
use PandoraFMS\Modules\Shared\Services\Audit;
final class UpdateGroupService
{
public function __construct(
private Audit $audit,
private GroupRepository $groupRepository,
private GroupValidation $groupValidation
) {
}
public function __invoke(Group $group, Group $oldGroup): Group
{
$this->groupValidation->__invoke($group, $oldGroup);
$group = $this->groupRepository->update($group);
$this->audit->write(
AUDIT_LOG_USER_MANAGEMENT,
'Update group '.$group->getIdGroup(),
json_encode($group->toArray())
);
return $group;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace PandoraFMS\Modules\Groups\Validations;
use PandoraFMS\Modules\Groups\Entities\Group;
use PandoraFMS\Modules\Groups\Services\ExistNameGroupService;
use PandoraFMS\Modules\Groups\Services\GetGroupService;
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
final class GroupValidation
{
public function __construct(
private ValidateAclSystem $acl,
private GetGroupService $getGroupService,
private ExistNameGroupService $existNameGroupService
) {
}
public function __invoke(Group $group, ?Group $oldGroup = null): void
{
if (!$group->getName()) {
throw new BadRequestException(__('Name is missing'));
}
if ($oldGroup === null || $oldGroup->getName() !== $group->getName()) {
if($this->existNameGroupService->__invoke($group->getName()) === true) {
throw new BadRequestException(
__('Name %s is already exists', $group->getName())
);
}
}
if ($oldGroup === null) {
$group->setIcon('without-group@groups.svg');
}
if ($group->getIsPropagate() === null) {
$group->setIsPropagate(false);
}
if ($group->getIsAlertEnabled() === null) {
$group->setIsAlertEnabled(true);
}
if ($group->getParent() === null) {
$group->setParent(0);
}
if (empty($group->getParent()) === false) {
$this->validateGroup($group->getParent());
$this->acl->validate($group->getParent(), 'AR', ' tried to read group');
}
if ($group->getIdSkin() === null) {
$group->setIdSkin(0);
}
if (empty($group->getIdSkin()) === false) {
$this->validateSkin($group->getIdSkin());
}
if ($group->getMaxAgents() === null) {
$group->setMaxAgents(0);
}
}
protected function validateGroup(int $idGroup): void
{
$this->getGroupService->__invoke($idGroup);
}
protected function validateSkin(int $idSkin): void
{
// TODO: create new service for this.
if (! (bool) \skins_search_skin_id($idSkin)) {
throw new BadRequestException(__('Invalid id skin'));
}
}
}

View File

@ -0,0 +1,16 @@
<?php
use PandoraFMS\Modules\Groups\Controllers\CreateGroupController;
use PandoraFMS\Modules\Groups\Controllers\DeleteGroupController;
use PandoraFMS\Modules\Groups\Controllers\GetGroupController;
use PandoraFMS\Modules\Groups\Controllers\ListGroupController;
use PandoraFMS\Modules\Groups\Controllers\UpdateGroupController;
use Slim\App;
return function (App $app) {
$app->map(['GET', 'POST'], '/group/list', ListGroupController::class);
$app->get('/group/{idGroup}', GetGroupController::class);
$app->post('/group', CreateGroupController::class);
$app->put('/group/{idGroup}', UpdateGroupController::class);
$app->delete('/group/{idGroup}', DeleteGroupController::class);
};

View File

@ -83,8 +83,11 @@ abstract class DataMapperAbstract
{
$strname = [
'PandoraFMS\\Modules\\Users\\Entities\\User' => 'User',
'PandoraFMS\\Modules\\Users\\Entities\\Profile' => 'Profile',
'PandoraFMS\\Modules\\Users\\UserProfiles\\Entities\\UserProfile' => 'UserProfile',
'PandoraFMS\\Modules\\Profiles\\Entities\\Profile' => 'Profile',
'PandoraFMS\\Modules\\Events\\Entities\\Event' => 'Event',
'PandoraFMS\\Modules\\Groups\\Entities\\Group' => 'Group',
'PandoraFMS\\Modules\\Tags\\Entities\\Tag' => 'Tag',
];
$result = ($strname[$this->getClassName()] ?? '');

View File

@ -6,8 +6,8 @@ use OpenApi\Annotations as OA;
/**
* @OA\Info(
* title="Nueva API de Pandora FMS",
* description="Lorem ipsum dolor sit amet consectetur, adipisicing elit. Libero, quibusdam esse commodi rem nisi cumque quos ut, exercitationem recusandae ipsam fuga qui veritatis non temporibus perferendis earum amet cupiditate eum nam corrupti! Dicta tempora, debitis molestiae corrupti sequi asperiores libero perferendis ut aperiam laboriosam repudiandae neque, rem quidem consectetur. Magnam illum perferendis aspernatur quibusdam esse? Libero eius veritatis quae perspiciatis. Sit recusandae aspernatur possimus autem! Corporis ipsa voluptatem placeat quasi praesentium esse doloremque magni, error, cumque vel, consequatur quam saepe iusto accusantium tempore ab dignissimos alias sint officia fuga voluptas. Vel repudiandae dicta ipsum repellat reprehenderit. Molestiae, ullam dolorum voluptatem necessitatibus itaque officiis ducimus consectetur aut facilis atque aliquid reiciendis voluptas sit incidunt, repellendus soluta quod obcaecati unde quas. Error officiis cumque vero minima amet modi enim, placeat consectetur cupiditate, fugiat odit sunt a earum natus dicta, labore id dolor! Quis laboriosam a quasi fuga! Ullam consectetur, voluptates repellat eveniet delectus officia nostrum amet obcaecati adipisci natus voluptas explicabo dolores similique doloribus. Rerum voluptatibus aperiam quidem necessitatibus, sint dignissimos natus delectus dolorem dicta sunt eum doloribus eligendi similique a at in repellat fuga voluptatem atque consectetur, ratione sit! Magni tenetur quos laborum, excepturi eveniet laboriosam optio aperiam eaque sit iusto.",
* title="API Pandora FMS",
* description="Documentacion para desarrolladores de la nueva api de pandora fms.",
* termsOfService="https://example.com/terms/",
* @OA\Contact(
* name="Pandorafms",
@ -37,36 +37,25 @@ use OpenApi\Annotations as OA;
* description="PandoraFMS API Server"
* ),
* @OA\Tag(
* name="Users",
* description="API Endpoints of users"
* name="Events",
* description="API Endpoints of events"
* ),
* @OA\Tag(
* name="Groups",
* description="API Endpoints of Groups"
* ),
* @OA\Tag(
* name="Profiles",
* description="API Endpoints of profiles"
* ),
* @OA\Tag(
* name="Events",
* description="API Endpoints of events"
* name="Tags",
* description="API Endpoints of tags"
* ),
* @OA\OpenApi(
* x={
* "tagGroups"= {
* {
* "name"="Users",
* "tags"={"Users"}
* },
* {
* "name"="Profiles",
* "tags"={"Profiles"}
* },
* {
* "name"="Events",
* "tags"={"Events"}
* },
* }
* }
* @OA\Tag(
* name="Users",
* description="API Endpoints of users"
* ),
*
* @OA\Parameter(
* parameter="parameterPage",
* name="page",

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Tags\Actions;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Services\CreateTagService;
final class CreateTagAction
{
public function __construct(
private CreateTagService $createTagService
) {
}
public function __invoke(Tag $tag): Tag
{
return $this->createTagService->__invoke($tag);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Tags\Actions;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Services\DeleteTagService;
final class DeleteTagAction
{
public function __construct(
private DeleteTagService $deleteTagService
) {
}
public function __invoke(Tag $tag): void
{
$this->deleteTagService->__invoke($tag);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Tags\Actions;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Services\GetTagService;
final class GetTagAction
{
public function __construct(
private GetTagService $getTagService
) {
}
public function __invoke(int $idTag): Tag
{
return $this->getTagService->__invoke($idTag);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace PandoraFMS\Modules\Tags\Actions;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Tags\Services\CountTagService;
use PandoraFMS\Modules\Tags\Services\ListTagService;
use PandoraFMS\Modules\Shared\Entities\PaginationData;
final class ListTagAction
{
public function __construct(
private ListTagService $listTagService,
private CountTagService $countTagService
) {
}
public function __invoke(TagFilter $tagFilter): array
{
return (new PaginationData(
$tagFilter->getPage(),
$tagFilter->getSizePage(),
$this->countTagService->__invoke($tagFilter),
$this->listTagService->__invoke($tagFilter)
))->toArray();
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Tags\Actions;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Services\UpdateTagService;
final class UpdateTagAction
{
public function __construct(
private UpdateTagService $updateTagService
) {
}
public function __invoke(Tag $tag, Tag $oldTag): Tag
{
return $this->updateTagService->__invoke($tag, $oldTag);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace PandoraFMS\Modules\Tags\Controllers;
use PandoraFMS\Modules\Tags\Actions\CreateTagAction;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class CreateTagController extends Controller
{
public function __construct(
private CreateTagAction $createTagAction,
private ValidateAclSystem $acl,
) {
}
/**
* @OA\Post(
* security={{ "bearerAuth": {}}},
* tags={"Tags"},
* path="/tag",
* summary="Creates a new tags",
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyTag"),
* @OA\Response(response=200, ref="#/components/responses/ResponseTag"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
// @var Tag $tag.
$tag = $this->fromRequest($request, Tag::class);
$this->acl->validate(0, 'UM', ' tried to manage tag');
$result = $this->createTagAction->__invoke($tag);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace PandoraFMS\Modules\Tags\Controllers;
use PandoraFMS\Modules\Tags\Actions\DeleteTagAction;
use PandoraFMS\Modules\Tags\Actions\GetTagAction;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class DeleteTagController extends Controller
{
public function __construct(
private DeleteTagAction $deleteTagAction,
private ValidateAclSystem $acl,
private GetTagAction $getTagAction
) {
}
/**
* @OA\Delete(
* security={{ "bearerAuth": {}}},
* tags={"Tags"},
* path="/tag/{idTag}",
* summary="Deletes an tag object.",
* @OA\Parameter(ref="#/components/parameters/parameterIdTag"),
* @OA\Response(response=200, ref="#/components/responses/successfullyDeleted"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
$idTag = $this->getParam($request, 'idTag');
$tag = $this->getTagAction->__invoke($idTag);
$this->acl->validate(0, 'UM', ' tried to manage tag');
$result = $this->deleteTagAction->__invoke($tag);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace PandoraFMS\Modules\Tags\Controllers;
use PandoraFMS\Modules\Tags\Actions\GetTagAction;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class GetTagController extends Controller
{
public function __construct(
private GetTagAction $getTagAction,
private ValidateAclSystem $acl
) {
}
/**
* @OA\Get(
* security={{ "bearerAuth": {}}},
* path="/tag/{idTag}",
* tags={"Tags"},
* summary="Show tag",
* @OA\Parameter(ref="#/components/parameters/parameterIdTag"),
* @OA\Response(response=200, ref="#/components/responses/ResponseTag"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
$idTag = $this->getParam($request, 'idTag');
$this->acl->validate(0, 'UM', ' tried to manage tag');
$result = $this->getTagAction->__invoke($idTag);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace PandoraFMS\Modules\Tags\Controllers;
use PandoraFMS\Modules\Tags\Actions\ListTagAction;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class ListTagController extends Controller
{
public function __construct(
private ListTagAction $listTagAction,
private ValidateAclSystem $acl,
) {
}
/**
* @OA\Post(
* security={{ "bearerAuth": {}}},
* tags={"Tags"},
* path="/tag/list",
* summary="List tags",
* @OA\Parameter(ref="#/components/parameters/parameterPage"),
* @OA\Parameter(ref="#/components/parameters/parameterSizePage"),
* @OA\Parameter(ref="#/components/parameters/parameterSortField"),
* @OA\Parameter(ref="#/components/parameters/parameterSortDirection"),
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyTagFilter"),
* @OA\Response(
* response="200",
* description="List Incidence object",
* content={
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="paginationData",
* type="object",
* ref="#/components/schemas/paginationData",
* description="Page object",
* ),
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(
* ref="#/components/schemas/Tag",
* description="Array of incidences Type objects"
* )
* ),
* ),
* )
* }
* ),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
public function __invoke(Request $request, Response $response): Response
{
// @var TagFilter $tagFilter.
$tagFilter = $this->fromRequest($request, TagFilter::class);
$this->acl->validate(0, 'UM', ' tried to manage tag');
$result = $this->listTagAction->__invoke($tagFilter);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace PandoraFMS\Modules\Tags\Controllers;
use PandoraFMS\Modules\Tags\Actions\GetTagAction;
use PandoraFMS\Modules\Tags\Actions\UpdateTagAction;
use PandoraFMS\Modules\Shared\Controllers\Controller;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* @OA\Put(
* security={{ "bearerAuth": {}}},
* path="/tag/{idTag}",
* tags={"Tags"},
* summary="Updates an tag",
* @OA\Parameter(ref="#/components/parameters/parameterIdTag"),
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyTag"),
* @OA\Response(response=200, ref="#/components/responses/ResponseTag"),
* @OA\Response(response=400, ref="#/components/responses/BadRequest"),
* @OA\Response(response=401, ref="#/components/responses/Unauthorized"),
* @OA\Response(response=403, ref="#/components/responses/Forbidden"),
* @OA\Response(response=404, ref="#/components/responses/NotFound"),
* @OA\Response(response=500, ref="#/components/responses/InternalServerError")
* )
*/
final class UpdateTagController extends Controller
{
public function __construct(
private UpdateTagAction $updateTagAction,
private ValidateAclSystem $acl,
private GetTagAction $getTagAction
) {
}
public function __invoke(Request $request, Response $response): Response
{
$idTag = $this->getParam($request, 'idTag');
$tag = $this->getTagAction->__invoke($idTag);
$oldTag = clone $tag;
$params = $this->extractParams($request);
$tag->fromArray($params);
$this->acl->validate(0, 'UM', ' tried to manage tag');
$result = $this->updateTagAction->__invoke($tag, $oldTag);
return $this->getResponse($response, $result);
}
}

View File

@ -0,0 +1,218 @@
<?php
namespace PandoraFMS\Modules\Tags\Entities;
use PandoraFMS\Modules\Shared\Entities\Entity;
use PandoraFMS\Modules\Shared\Validators\Validator;
/**
* @OA\Schema(
* schema="Tag",
* type="object",
* @OA\Property(
* property="idTag",
* type="integer",
* nullable=false,
* description="Id Tag",
* readOnly=true
* ),
* @OA\Property(
* property="name",
* type="string",
* nullable=false,
* default=null,
* description="Name of the tag"
* ),
* @OA\Property(
* property="description",
* type="string",
* nullable=true,
* default=null,
* description="Description of the tag"
* ),
* @OA\Property(
* property="url",
* type="string",
* nullable=true,
* default=null,
* description="Url of the tag"
* ),
* @OA\Property(
* property="phone",
* type="string",
* nullable=true,
* default=null,
* description="Phone of the tag"
* ),
* @OA\Property(
* property="previousName",
* type="string",
* nullable=true,
* default=null,
* description="Previous name of the tag",
* readOnly=true,
* deprecated=true
* )
* )
*
* @OA\Response(
* response="ResponseTag",
* description="Tag object",
* content={
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* ref="#/components/schemas/Tag",
* description="Tag object"
* )
* )
* }
* )
*
* @OA\Parameter(
* parameter="parameterIdTag",
* name="idTag",
* in="path",
* description="Tag id",
* required=true,
* @OA\Schema(
* type="integer",
* default=1
* )
* )
*
* @OA\RequestBody(
* request="requestBodyTag",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/Tag")
* )
* )
*/
final class Tag extends Entity
{
private ?int $idTag = null;
private ?string $name = null;
private ?string $description = null;
private ?string $url = null;
private ?string $mail = null;
private ?string $phone = null;
private ?string $previousName = null;
public function __construct()
{
}
public function fieldsReadOnly(): array
{
return [
'idTag' => 1,
'previousName' => 1,
];
}
public function jsonSerialize(): mixed
{
return [
'idTag' => $this->getIdTag(),
'name' => $this->getName(),
'description' => $this->getDescription(),
'url' => $this->getUrl(),
'mail' => $this->getMail(),
'phone' => $this->getPhone(),
];
}
public function getValidations(): array
{
return [
'idTag' => [
Validator::INTEGER,
Validator::GREATERTHAN,
],
'name' => Validator::STRING,
'description' => Validator::STRING,
'url' => Validator::STRING,
'mail' => Validator::MAIL,
'phone' => Validator::STRING,
'previousName' => Validator::STRING,
];
}
public function validateFields(array $filters): array
{
return (new Validator())->validate($filters);
}
public function getIdTag(): ?int
{
return $this->idTag;
}
public function setIdTag(?int $idTag): self
{
$this->idTag = $idTag;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getUrl(): ?string
{
return $this->url;
}
public function setUrl(?string $url): self
{
$this->url = $url;
return $this;
}
public function getMail(): ?string
{
return $this->mail;
}
public function setMail(?string $mail): self
{
$this->mail = $mail;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getPreviousName(): ?string
{
return $this->previousName;
}
public function setPreviousName(?string $previousName): self
{
$this->previousName = $previousName;
return $this;
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace PandoraFMS\Modules\Tags\Entities;
use PandoraFMS\Modules\Shared\Builders\Builder;
use PandoraFMS\Modules\Shared\Core\DataMapperAbstract;
use PandoraFMS\Modules\Shared\Core\MappeableInterface;
use PandoraFMS\Modules\Shared\Repositories\Repository;
final class TagDataMapper extends DataMapperAbstract
{
public const TABLE_NAME = 'ttag';
public const ID_TAG = 'id_tag';
public const NAME = 'name';
public const DESCRIPTION = 'description';
public const URL = 'url';
public const MAIL = 'email';
public const PHONE = 'phone';
public const PREVIOUS_NAME = 'previous_name';
public function __construct(
private Repository $repository,
private Builder $builder,
) {
parent::__construct(
self::TABLE_NAME,
self::ID_TAG,
);
}
public function getClassName(): string
{
return Tag::class;
}
public function fromDatabase(array $data): Tag
{
return $this->builder->build(new Tag(), [
'idTag' => $data[self::ID_TAG],
'name' => $this->repository->safeOutput($data[self::NAME]),
'description' => $this->repository->safeOutput($data[self::DESCRIPTION]),
'url' => $this->repository->safeOutput($data[self::URL]),
'mail' => $this->repository->safeOutput($data[self::MAIL]),
'phone' => $this->repository->safeOutput($data[self::PHONE]),
'previousName' => $this->repository->safeOutput($data[self::PREVIOUS_NAME]),
]);
}
public function toDatabase(MappeableInterface $data): array
{
/** @var Tag $data */
return [
self::ID_TAG => $data->getIdTag(),
self::NAME => $this->repository->safeInput($data->getName()),
self::DESCRIPTION => $this->repository->safeInput($data->getDescription()),
self::URL => $this->repository->safeInput($data->getUrl()),
self::MAIL => $this->repository->safeInput($data->getMail()),
self::PHONE => $this->repository->safeInput($data->getPhone()),
self::PREVIOUS_NAME => $this->repository->safeInput($data->getPreviousName()),
];
}
}

View File

@ -0,0 +1,123 @@
<?php
namespace PandoraFMS\Modules\Tags\Entities;
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
use PandoraFMS\Modules\Shared\Validators\Validator;
/**
* @OA\Schema(
* schema="TagFilter",
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/Tag"),
* @OA\Schema(
* @OA\Property(
* property="idTag",
* default=null,
* readOnly=false
* ),
* @OA\Property(
* property="freeSearch",
* type="string",
* nullable=true,
* default=null,
* description="Find word in name field."
* )
* )
* }
* )
*
* @OA\RequestBody(
* request="requestBodyTagFilter",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/TagFilter")
* ),
* )
*/
final class TagFilter extends FilterAbstract
{
private ?string $freeSearch = null;
public function __construct()
{
$this->setDefaultFieldOrder(TagDataMapper::NAME);
$this->setDefaultDirectionOrder($this::ASC);
$this->setEntityFilter(new Tag());
}
public function fieldsTranslate(): array
{
return [
'idTag' => TagDataMapper::ID_TAG,
'name' => TagDataMapper::NAME,
'description' => TagDataMapper::DESCRIPTION,
'url' => TagDataMapper::URL,
'mail' => TagDataMapper::MAIL,
'phone' => TagDataMapper::PHONE,
'previousName' => TagDataMapper::PREVIOUS_NAME,
];
}
public function fieldsReadOnly(): array
{
return ['previousName' => 1];
}
public function jsonSerialize(): mixed
{
return [
'freeSearch' => $this->getFreeSearch(),
];
}
public function getValidations(): array
{
$validations = [];
if($this->getEntityFilter() !== null) {
$validations = $this->getEntityFilter()->getValidations();
}
$validations['freeSearch'] = Validator::STRING;
return $validations;
}
public function validateFields(array $filters): array
{
return (new Validator())->validate($filters);
}
/**
* Get the value of freeSearch.
*
* @return ?string
*/
public function getFreeSearch(): ?string
{
return $this->freeSearch;
}
/**
* Set the value of freeSearch.
*
* @param ?string $freeSearch
*
*/
public function setFreeSearch(?string $freeSearch): self
{
$this->freeSearch = $freeSearch;
return $this;
}
/**
* Get the value of fieldsFreeSearch.
*
* @return ?array
*/
public function getFieldsFreeSearch(): ?array
{
return [TagDataMapper::NAME, TagDataMapper::DESCRIPTION];
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace PandoraFMS\Modules\Tags\Repositories;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Entities\TagDataMapper;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Shared\Repositories\Repository;
class TagRepository
{
public function __construct(
private Repository $repository,
private TagDataMapper $tagDataMapper
) {
}
/**
* @return Tag[],
*/
public function list(TagFilter $tagFilter): array
{
return $this->repository->__list(
$tagFilter,
$this->tagDataMapper
);
}
public function count(TagFilter $tagFilter): int
{
return $this->repository->__count(
$tagFilter,
$this->tagDataMapper
);
}
public function getOne(TagFilter $tagFilter): Tag
{
return $this->repository->__getOne(
$tagFilter,
$this->tagDataMapper
);
}
public function create(Tag $tag): Tag
{
$id = $this->repository->__create($tag, $this->tagDataMapper);
return $tag->setIdTag($id);
}
public function update(Tag $tag): Tag
{
return $this->repository->__update(
$tag,
$this->tagDataMapper,
$tag->getIdTag()
);
}
public function delete(int $id): void
{
$this->repository->__delete($id, $this->tagDataMapper);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
final class CountTagService
{
public function __construct(
private TagRepository $tagRepository,
) {
}
public function __invoke(TagFilter $tagFilter): int
{
return $this->tagRepository->count($tagFilter);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
use PandoraFMS\Modules\Tags\Validations\TagValidation;
use PandoraFMS\Modules\Shared\Services\Audit;
final class CreateTagService
{
public function __construct(
private Audit $audit,
private TagRepository $tagRepository,
private TagValidation $tagValidation
) {
}
public function __invoke(Tag $tag): Tag
{
$this->tagValidation->__invoke($tag);
$tag = $this->tagRepository->create($tag);
$this->audit->write(
AUDIT_LOG_TAG_MANAGEMENT,
'Create tag '.$tag->getName(),
json_encode($tag->toArray())
);
return $tag;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
use PandoraFMS\Modules\Shared\Services\Audit;
final class DeleteTagService
{
public function __construct(
private Audit $audit,
private TagRepository $tagRepository,
) {
}
public function __invoke(Tag $tag): void
{
$idTag = $tag->getIdTag();
$nameTag = $tag->getName();
$this->tagRepository->delete($idTag);
$this->audit->write(
AUDIT_LOG_TAG_MANAGEMENT,
'Deleted tag '.$nameTag
);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
use PandoraFMS\Modules\Shared\Exceptions\NotFoundException;
final class ExistNameTagService
{
public function __construct(
private TagRepository $tagRepository,
) {
}
public function __invoke(string $name): bool
{
$tagFilter = new TagFilter();
/** @var Tag $entityFilter */
$entityFilter = $tagFilter->getEntityFilter();
$entityFilter->setName($name);
try {
$this->tagRepository->getOne($tagFilter);
return true;
} catch (NotFoundException) {
return false;
}
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
final class GetTagService
{
public function __construct(
private TagRepository $tagRepository,
) {
}
public function __invoke(int $idTag): Tag
{
$tagFilter = new TagFilter();
/** @var Tag $entityFilter */
$entityFilter = $tagFilter->getEntityFilter();
$entityFilter->setIdTag($idTag);
return $this->tagRepository->getOne($tagFilter);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\TagFilter;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
final class ListTagService
{
public function __construct(
private TagRepository $tagRepository,
) {
}
public function __invoke(TagFilter $tagFilter): array
{
return $this->tagRepository->list($tagFilter);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace PandoraFMS\Modules\Tags\Services;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Repositories\TagRepository;
use PandoraFMS\Modules\Tags\Validations\TagValidation;
use PandoraFMS\Modules\Shared\Services\Audit;
final class UpdateTagService
{
public function __construct(
private Audit $audit,
private TagRepository $tagRepository,
private TagValidation $tagValidation
) {
}
public function __invoke(Tag $tag, Tag $oldTag): Tag
{
$this->tagValidation->__invoke($tag, $oldTag);
$tag = $this->tagRepository->update($tag);
$this->audit->write(
AUDIT_LOG_TAG_MANAGEMENT,
'Update tag '.$tag->getName(),
json_encode($tag->toArray())
);
return $tag;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace PandoraFMS\Modules\Tags\Validations;
use PandoraFMS\Modules\Tags\Entities\Tag;
use PandoraFMS\Modules\Tags\Services\ExistNameTagService;
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
final class TagValidation
{
public function __construct(
private ExistNameTagService $existNameTagService
) {
}
public function __invoke(Tag $tag, ?Tag $oldTag = null): void
{
if (!$tag->getName()) {
throw new BadRequestException(__('Name is missing'));
}
if($oldTag === null || $oldTag->getName() !== $tag->getName()) {
if($this->existNameTagService->__invoke($tag->getName()) === true) {
throw new BadRequestException(
__('Name %s is already exists', $tag->getName())
);
}
}
//if($tag->getIsAgentView() === null) {
// $tag->setIsAgentView(false);
//}
}
}

View File

@ -0,0 +1,16 @@
<?php
use PandoraFMS\Modules\Tags\Controllers\CreateTagController;
use PandoraFMS\Modules\Tags\Controllers\DeleteTagController;
use PandoraFMS\Modules\Tags\Controllers\GetTagController;
use PandoraFMS\Modules\Tags\Controllers\ListTagController;
use PandoraFMS\Modules\Tags\Controllers\UpdateTagController;
use Slim\App;
return function (App $app) {
$app->map(['GET', 'POST'], '/tag/list', ListTagController::class);
$app->get('/tag/{idTag}', GetTagController::class);
$app->post('/tag', CreateTagController::class);
$app->put('/tag/{idTag}', UpdateTagController::class);
$app->delete('/tag/{idTag}', DeleteTagController::class);
};

View File

@ -2,11 +2,12 @@
namespace PandoraFMS\Modules\Users\UserProfiles\Validations;
//use PandoraFMS\Modules\Groups\Services\GetGroupService;
use PandoraFMS\Modules\Groups\Services\GetGroupService;
use PandoraFMS\Modules\Profiles\Services\GetProfileService;
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
use PandoraFMS\Modules\Shared\Services\Config;
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
use PandoraFMS\Modules\Tags\Services\GetTagService;
use PandoraFMS\Modules\Users\Services\GetUserService;
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfile;
use PandoraFMS\Modules\Users\UserProfiles\Services\ExistUserProfileService;
@ -14,10 +15,11 @@ use PandoraFMS\Modules\Users\UserProfiles\Services\ExistUserProfileService;
final class UserProfileValidation
{
public function __construct(
//private GetGroupService $getGroupService,
private GetGroupService $getGroupService,
private GetUserService $getUserService,
private GetProfileService $getProfileService,
private ExistUserProfileService $existUserProfileService,
private GetTagService $getTagService,
private ValidateAclSystem $acl,
private Config $config
) {
@ -82,9 +84,9 @@ final class UserProfileValidation
$this->getProfileService->__invoke($idProfile);
}
private function validateGroup(int $idGroup): void
protected function validateGroup(int $idGroup): void
{
//$this->getGroupService->__invoke($idGroup);
$this->getGroupService->__invoke($idGroup);
}
protected function validatePolicy(int $idPolicy): void
@ -97,11 +99,8 @@ final class UserProfileValidation
protected function validateTags(array $tags): void
{
// TODO: create new service for this.
foreach ($tags as $tag) {
if (! (bool) \tags_get_name($tag)) {
throw new BadRequestException(__('Invalid id tag:, %', $tag));
}
$this->getTagService->__invoke((int) $tag);
}
}
}