mirror of
https://github.com/pandorafms/pandorafms.git
synced 2025-07-28 16:24:54 +02:00
new api 2.0
This commit is contained in:
parent
3a509b9415
commit
b2a5472be3
BIN
pandora_console/api/documentation/favicon-16x16.png
Normal file
BIN
pandora_console/api/documentation/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
pandora_console/api/documentation/favicon-32x32.png
Normal file
BIN
pandora_console/api/documentation/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
16
pandora_console/api/documentation/index.css
Normal file
16
pandora_console/api/documentation/index.css
Normal file
@ -0,0 +1,16 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
29
pandora_console/api/documentation/index.html
Normal file
29
pandora_console/api/documentation/index.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="./favicon-32x32.png"
|
||||
sizes="32x32"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="./favicon-16x16.png"
|
||||
sizes="16x16"
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"></script>
|
||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"></script>
|
||||
<script src="./swagger-initializer.js" charset="UTF-8"></script>
|
||||
</body>
|
||||
</html>
|
95
pandora_console/api/documentation/oauth2-redirect.html
Normal file
95
pandora_console/api/documentation/oauth2-redirect.html
Normal file
@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
function run() {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1).replace("?", "&");
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&");
|
||||
arr.forEach(function(v, i, _arr) {
|
||||
_arr[i] = '"' + v.replace("=", '":"') + '"';
|
||||
});
|
||||
qp = qp
|
||||
? JSON.parse("{" + arr.join() + "}", function(key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value);
|
||||
})
|
||||
: {};
|
||||
|
||||
isValid = qp.state === sentState;
|
||||
|
||||
if (
|
||||
(oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorization_code") &&
|
||||
!oauth2.auth.code
|
||||
) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message:
|
||||
"Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({ auth: oauth2.auth, redirectUrl: redirectUrl });
|
||||
} else {
|
||||
let oauthErrorMsg;
|
||||
if (qp.error) {
|
||||
oauthErrorMsg =
|
||||
"[" +
|
||||
qp.error +
|
||||
"]: " +
|
||||
(qp.error_description
|
||||
? qp.error_description + ". "
|
||||
: "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: " + qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message:
|
||||
oauthErrorMsg ||
|
||||
"[Authorization failed]: no accessCode received from the server."
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({
|
||||
auth: oauth2.auth,
|
||||
token: qp,
|
||||
isValid: isValid,
|
||||
redirectUrl: redirectUrl
|
||||
});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
if (document.readyState !== "loading") {
|
||||
run();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
run();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
41
pandora_console/api/documentation/swagger-initializer.js
Normal file
41
pandora_console/api/documentation/swagger-initializer.js
Normal file
@ -0,0 +1,41 @@
|
||||
window.onload = function() {
|
||||
//<editor-fold desc="Changeable Configuration Block">
|
||||
const UrlMutatorPlugin = system => ({
|
||||
rootInjects: {
|
||||
setServer: server => {
|
||||
const jsonSpec = system.getState().toJSON().spec.json;
|
||||
const endpoint = window.location.pathname.replace(
|
||||
"/api/documentation/",
|
||||
""
|
||||
);
|
||||
const servers = [
|
||||
{
|
||||
url: endpoint + jsonSpec.servers[0].url,
|
||||
description: "Integria API"
|
||||
}
|
||||
];
|
||||
const newJsonSpec = Object.assign({}, jsonSpec, { servers });
|
||||
|
||||
return system.specActions.updateJsonSpec(newJsonSpec);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "../v1/swagger.json",
|
||||
dom_id: "#swagger-ui",
|
||||
docExpansion: "none",
|
||||
deepLinking: true,
|
||||
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
|
||||
plugins: [SwaggerUIBundle.plugins.DownloadUrl, UrlMutatorPlugin],
|
||||
layout: "StandaloneLayout",
|
||||
onComplete: () => {
|
||||
window.ui.setServer();
|
||||
}
|
||||
});
|
||||
|
||||
window.ui = ui;
|
||||
|
||||
//</editor-fold>
|
||||
};
|
68018
pandora_console/api/documentation/swagger-ui-bundle.js
Normal file
68018
pandora_console/api/documentation/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
21088
pandora_console/api/documentation/swagger-ui-es-bundle-core.js
Normal file
21088
pandora_console/api/documentation/swagger-ui-es-bundle-core.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
66986
pandora_console/api/documentation/swagger-ui-es-bundle.js
Normal file
66986
pandora_console/api/documentation/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
19361
pandora_console/api/documentation/swagger-ui-standalone-preset.js
Normal file
19361
pandora_console/api/documentation/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8994
pandora_console/api/documentation/swagger-ui.css
Normal file
8994
pandora_console/api/documentation/swagger-ui.css
Normal file
File diff suppressed because it is too large
Load Diff
1
pandora_console/api/documentation/swagger-ui.css.map
Normal file
1
pandora_console/api/documentation/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
15495
pandora_console/api/documentation/swagger-ui.js
Normal file
15495
pandora_console/api/documentation/swagger-ui.js
Normal file
File diff suppressed because it is too large
Load Diff
1
pandora_console/api/documentation/swagger-ui.js.map
Normal file
1
pandora_console/api/documentation/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
1
pandora_console/api/index.html
Normal file
1
pandora_console/api/index.html
Normal file
@ -0,0 +1 @@
|
||||
<meta http-equiv="REFRESH" content="0; url=documentation" />
|
5
pandora_console/api/v1/.htaccess
Normal file
5
pandora_console/api/v1/.htaccess
Normal file
@ -0,0 +1,5 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
</IfModule>
|
25
pandora_console/api/v1/config/bootstrap.php
Normal file
25
pandora_console/api/v1/config/bootstrap.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use DI\ContainerBuilder;
|
||||
use Slim\App;
|
||||
|
||||
require_once __DIR__.'/includeDependencies.php';
|
||||
|
||||
$containerBuilder = new ContainerBuilder();
|
||||
|
||||
// Add DI container definitions.
|
||||
$containerBuilder->addDefinitions(__DIR__.'/container.php');
|
||||
|
||||
// Create DI container instance.
|
||||
$container = $containerBuilder->build();
|
||||
|
||||
// Create Slim App instance.
|
||||
$app = $container->get(App::class);
|
||||
|
||||
// Set attachment directory.
|
||||
$config['attachment_directory'] = __DIR__.'/../../../attachment';
|
||||
|
||||
// Register routes.
|
||||
(require __DIR__.'/routes.php')($app);
|
||||
|
||||
return $app;
|
42
pandora_console/api/v1/config/container.php
Normal file
42
pandora_console/api/v1/config/container.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use PandoraFMS\Modules\Shared\Repositories\Repository;
|
||||
use PandoraFMS\Modules\Shared\Repositories\RepositoryMySQL;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepositoryMySQL;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Slim\App;
|
||||
use Slim\Factory\AppFactory;
|
||||
|
||||
return [
|
||||
'settings' => function () {
|
||||
return include __DIR__.'/settings.php';
|
||||
},
|
||||
App::class => function (ContainerInterface $container) {
|
||||
AppFactory::setContainer($container);
|
||||
|
||||
$app = AppFactory::create();
|
||||
|
||||
$basePath = rtrim(
|
||||
preg_replace(
|
||||
'/(.*)public\/.*/',
|
||||
'$1',
|
||||
$_SERVER['SCRIPT_NAME']
|
||||
),
|
||||
'/'
|
||||
);
|
||||
|
||||
$app->setBasePath($basePath);
|
||||
|
||||
// Register middleware.
|
||||
(include __DIR__.'/middleware.php')($app, $container);
|
||||
|
||||
return $app;
|
||||
},
|
||||
Repository::class => function (ContainerInterface $container) {
|
||||
return $container->get(RepositoryMySQL::class);
|
||||
},
|
||||
UserRepository::class => function (ContainerInterface $container) {
|
||||
return $container->get(UserRepositoryMySQL::class);
|
||||
},
|
||||
];
|
20
pandora_console/api/v1/config/generateDoc.php
Normal file
20
pandora_console/api/v1/config/generateDoc.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/../../../vendor/autoload.php';
|
||||
|
||||
$exclude = ['tests'];
|
||||
$pattern = '*.php';
|
||||
|
||||
$openapi = \OpenApi\Generator::scan(
|
||||
\OpenApi\Util::finder(
|
||||
[
|
||||
__DIR__.'/..',
|
||||
__DIR__.'/../../../include/lib/Modules',
|
||||
],
|
||||
$exclude,
|
||||
$pattern
|
||||
)
|
||||
);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
file_put_contents(__DIR__.'/../public/swagger.json', $openapi->toJson());
|
10
pandora_console/api/v1/config/includeDependencies.php
Normal file
10
pandora_console/api/v1/config/includeDependencies.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/../../../vendor/autoload.php';
|
||||
require_once __DIR__.'/../../../include/config.php';
|
||||
global $config;
|
||||
|
||||
if (file_exists($config['homedir'].'/'.ENTERPRISE_DIR.'/load_enterprise.php') === true) {
|
||||
include_once $config['homedir'].'/'.ENTERPRISE_DIR.'/load_enterprise.php';
|
||||
include_once $config['homedir'].'/'.ENTERPRISE_DIR.'/include/functions_login.php';
|
||||
}
|
103
pandora_console/api/v1/config/middleware.php
Normal file
103
pandora_console/api/v1/config/middleware.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
// use PandoraFMS\Modules\Shared\Middlewares\UserTokenMiddleware;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Slim\App;
|
||||
|
||||
return function (App $app, ContainerInterface $container) {
|
||||
// Parse json, form data and xml.
|
||||
$app->addBodyParsingMiddleware();
|
||||
|
||||
// Add the Slim built-in routing middleware.
|
||||
$app->addRoutingMiddleware();
|
||||
|
||||
// Authenticate Integria.
|
||||
$beforeMiddleware = function (
|
||||
Request $request,
|
||||
RequestHandler $handler
|
||||
) use (
|
||||
$app,
|
||||
$container
|
||||
) {
|
||||
global $config;
|
||||
$authorization = $request->getHeader('Authorization');
|
||||
$user = false;
|
||||
if (empty($authorization) === false && empty($authorization[0]) === false) {
|
||||
$bearer = explode('Bearer ', $authorization[0]);
|
||||
if (empty($bearer) === false && isset($bearer[1]) === true) {
|
||||
// $user = \get_db_value(
|
||||
// 'id_usuario',
|
||||
// 'tusuario',
|
||||
// 'api_key',
|
||||
// $bearer[1]
|
||||
// );
|
||||
if ($user !== false) {
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION['id_usuario'] = $user;
|
||||
$config['id_user'] = $user;
|
||||
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
session_write_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$user = 'admin';
|
||||
$_SESSION['id_usuario'] = $user;
|
||||
$config['id_user'] = $user;
|
||||
|
||||
if (empty($user) === true) {
|
||||
// $userTokenMiddleware = $container->get(UserTokenMiddleware::class);
|
||||
// if ($userTokenMiddleware->check($request) === false) {
|
||||
$response = $app->getResponseFactory()->createResponse();
|
||||
$response->getBody()->write(
|
||||
json_encode(['error' => 'You need to be authenticated to perform this action'])
|
||||
);
|
||||
|
||||
$errorCode = 401;
|
||||
$newResponse = $response->withStatus($errorCode);
|
||||
return $newResponse;
|
||||
}
|
||||
|
||||
$response = $handler->handle($request);
|
||||
return $response;
|
||||
};
|
||||
|
||||
$app->add($beforeMiddleware);
|
||||
|
||||
// Handle exceptions.
|
||||
// Define Custom Error Handler.
|
||||
$customErrorHandler = function (
|
||||
Request $request,
|
||||
Throwable $exception,
|
||||
bool $displayErrorDetails,
|
||||
bool $logErrors,
|
||||
bool $logErrorDetails,
|
||||
?LoggerInterface $logger=null
|
||||
) use ($app) {
|
||||
$logger?->error($exception->getMessage());
|
||||
$response = $app->getResponseFactory()->createResponse();
|
||||
$response->getBody()->write(
|
||||
json_encode(['error' => $exception->getMessage()])
|
||||
);
|
||||
|
||||
$errorCode = 500;
|
||||
if (empty($exception->getCode()) === false) {
|
||||
$errorCode = $exception->getCode();
|
||||
}
|
||||
|
||||
$newResponse = $response->withStatus($errorCode);
|
||||
return $newResponse;
|
||||
};
|
||||
|
||||
// Add Error Middleware.
|
||||
// $errorMiddleware = $app->addErrorMiddleware(true, true, true);
|
||||
// $errorMiddleware->setDefaultErrorHandler($customErrorHandler);
|
||||
};
|
7
pandora_console/api/v1/config/routes.php
Normal file
7
pandora_console/api/v1/config/routes.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Slim\App;
|
||||
|
||||
return function (App $app) {
|
||||
(include __DIR__.'/../../../include/lib/Modules/Users/routes.php')($app);
|
||||
};
|
10
pandora_console/api/v1/config/settings.php
Normal file
10
pandora_console/api/v1/config/settings.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
require __DIR__.'/../../../include/config.php';
|
||||
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', $config['homedir'].'/log/console.log');
|
||||
|
||||
return [];
|
7
pandora_console/api/v1/public/.htaccess
Normal file
7
pandora_console/api/v1/public/.htaccess
Normal file
@ -0,0 +1,7 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
</IfModule>
|
3
pandora_console/api/v1/public/index.php
Normal file
3
pandora_console/api/v1/public/index.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
(require __DIR__.'/../config/bootstrap.php')->run();
|
1167
pandora_console/api/v1/public/swagger.json
Normal file
1167
pandora_console/api/v1/public/swagger.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@
|
||||
],
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.0.2"
|
||||
"php": "8.1"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
@ -18,7 +18,16 @@
|
||||
"amphp/parallel-functions": "^1.0",
|
||||
"chrome-php/chrome": "^1.8.1",
|
||||
"artica/phpchartjs": "^1.0",
|
||||
"tinymce/tinymce": "^6.4"
|
||||
"tinymce/tinymce": "^6.4",
|
||||
"slim/slim": "4.*",
|
||||
"slim/psr7": "^1.6",
|
||||
"nyholm/psr7": "^1.8",
|
||||
"nyholm/psr7-server": "^1.1",
|
||||
"guzzlehttp/psr7": "^2",
|
||||
"laminas/laminas-diactoros": "^3.2",
|
||||
"php-di/php-di": "^7.0",
|
||||
"zircote/swagger-php": "^4.8",
|
||||
"doctrine/annotations": "^2.0"
|
||||
},
|
||||
"repositories": {
|
||||
"phpchartjs": {
|
||||
|
1881
pandora_console/composer.lock
generated
1881
pandora_console/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Builders;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Entities\Entity;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
|
||||
class Builder
|
||||
{
|
||||
|
||||
|
||||
public function build(Entity $entity, array $data): Entity
|
||||
{
|
||||
foreach ($data as $field => $value) {
|
||||
if (method_exists($entity, 'set'.ucfirst($field)) === false) {
|
||||
throw new BadRequestException(__('Not exists method set%s', ucfirst($field)));
|
||||
}
|
||||
|
||||
$entity->{'set'.ucfirst($field)}($value);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Core\SerializableAbstract;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\ForbiddenActionException;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\InvalidClassException;
|
||||
|
||||
use Nyholm\Psr7\Stream;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Slim\Routing\RouteContext;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function getParam(Request $request, string $param): mixed
|
||||
{
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$route = $routeContext->getRoute();
|
||||
$value = $route->getArgument($param);
|
||||
|
||||
if (empty($value) === true) {
|
||||
throw new BadRequestException(__('Parameter %s is required as an argument', $param));
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public function getFile(Request $request, string $file): UploadedFileInterface
|
||||
{
|
||||
$files = $request->getUploadedFiles();
|
||||
if (isset($files[$file]) === false || empty($files[$file]) === true) {
|
||||
throw new BadRequestException(__('File %s is required as an argument', $file));
|
||||
}
|
||||
|
||||
if ($files[$file]->getError() !== UPLOAD_ERR_OK) {
|
||||
throw new BadRequestException(__('Error upload file'));
|
||||
}
|
||||
|
||||
return $files[$file];
|
||||
}
|
||||
|
||||
|
||||
public function extractParams(Request $request): array
|
||||
{
|
||||
$queryParams = ($request->getQueryParams() ?? []);
|
||||
$parsedBody = ($request->getParsedBody() ?? []);
|
||||
// if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
// throw new \UnexpectedValueException(sprintf(
|
||||
// 'Cannot decoded body JSON, error: %s',
|
||||
// json_last_error_msg()
|
||||
// ));
|
||||
// }
|
||||
$params = array_merge($queryParams, $parsedBody);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
|
||||
public function fromRequest(Request $request, string $className): mixed
|
||||
{
|
||||
$params = $this->extractParams($request);
|
||||
|
||||
if (class_exists($className) === false) {
|
||||
throw new InvalidClassException(__('Class %s is not defined', $className));
|
||||
}
|
||||
|
||||
$class = new $className();
|
||||
|
||||
if (!$class instanceof SerializableAbstract) {
|
||||
throw new InvalidClassException(__('Class %s is not instance of Serializable abstract', $className));
|
||||
}
|
||||
|
||||
return $class->fromArray($params);
|
||||
}
|
||||
|
||||
|
||||
public function getResponse(
|
||||
Response $response,
|
||||
mixed $result,
|
||||
?string $contentType='application/json'
|
||||
): Response {
|
||||
if ($contentType === 'application/json') {
|
||||
$result = json_encode($result);
|
||||
}
|
||||
|
||||
$response->getBody()->write($result);
|
||||
return $response->withHeader('Content-Type', $contentType);
|
||||
}
|
||||
|
||||
|
||||
public function getResponseAttachment(Response $response, string $path, string $fileName)
|
||||
{
|
||||
try {
|
||||
ob_clean();
|
||||
$stream = fopen($path, 'r');
|
||||
$file_stream = Stream::create($stream);
|
||||
} catch (\Throwable $th) {
|
||||
throw new ForbiddenActionException(
|
||||
__('Error download file: ').$th->getMessage(),
|
||||
empty($th->getCode()) === true ? HttpCodesEnum::BAD_REQUEST : $th->getCode()
|
||||
);
|
||||
}
|
||||
|
||||
return $response->withBody($file_stream)->withHeader('Content-Disposition', 'attachment; filename='.$fileName)->withHeader('Content-Type', mime_content_type($path));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Core;
|
||||
|
||||
abstract class DataMapperAbstract
|
||||
{
|
||||
|
||||
private null|string $tableRelated = null;
|
||||
|
||||
private null|string $keyRelated = null;
|
||||
|
||||
private null|string $searchFieldRelated = null;
|
||||
|
||||
private mixed $searchFieldValueRelated = null;
|
||||
|
||||
|
||||
public function __construct(
|
||||
private string $tableName,
|
||||
private string $primaryKey
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
abstract public function getClassName(): string;
|
||||
|
||||
|
||||
abstract public function fromDatabase(array $data): MappeableInterface;
|
||||
|
||||
|
||||
abstract public function toDatabase(MappeableInterface $data): array;
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of tableName.
|
||||
*/
|
||||
public function getTableName(): string
|
||||
{
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of primaryKey.
|
||||
*/
|
||||
public function getPrimaryKey(): string
|
||||
{
|
||||
return $this->primaryKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of tableRelated.
|
||||
*/
|
||||
public function getTableRelated(): null|string
|
||||
{
|
||||
return $this->tableRelated;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of tableRelated.
|
||||
*/
|
||||
public function setTableRelated(null|string $tableRelated): self
|
||||
{
|
||||
$this->tableRelated = $tableRelated;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of keyRelated.
|
||||
*/
|
||||
public function getKeyRelated(): null|string
|
||||
{
|
||||
return $this->keyRelated;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of keyRelated.
|
||||
*/
|
||||
public function setKeyRelated(null|string $keyRelated): self
|
||||
{
|
||||
$this->keyRelated = $keyRelated;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of searchFieldRelated.
|
||||
*/
|
||||
public function getSearchFieldRelated(): null|string
|
||||
{
|
||||
return $this->searchFieldRelated;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of searchFieldRelated.
|
||||
*/
|
||||
public function setSearchFieldRelated(null|string $searchFieldRelated): self
|
||||
{
|
||||
$this->searchFieldRelated = $searchFieldRelated;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of searchFieldValueRelated.
|
||||
*/
|
||||
public function getSearchFieldValueRelated(): mixed
|
||||
{
|
||||
return $this->searchFieldValueRelated;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of searchFieldValueRelated.
|
||||
*/
|
||||
public function setSearchFieldValueRelated(mixed $searchFieldValueRelated): self
|
||||
{
|
||||
$this->searchFieldValueRelated = $searchFieldValueRelated;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getStringNameClass(): string
|
||||
{
|
||||
$strname = [
|
||||
'PandoraFMS\\Modules\\Users\\Entities\\User' => 'User',
|
||||
'PandoraFMS\\Modules\\Shared\\Workunits\\Entities\\Workunit' => 'Workunit',
|
||||
'PandoraFMS\\Modules\\Shared\\Attachments\\Entities\\Attachment' => 'Attachment',
|
||||
'PandoraFMS\\Modules\\Users\\UserProfiles\\Entities\\UserProfile' => 'Profile',
|
||||
'PandoraFMS\\Modules\\Profiles\\Entities\\Profile' => 'Profile',
|
||||
'PandoraFMS\\Modules\\Groups\\Entities\\Group' => 'Group',
|
||||
];
|
||||
|
||||
$result = ($strname[$this->getClassName()] ?? '');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Core;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Entities\Entity;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\InvalidFilterException;
|
||||
use PandoraFMS\Modules\Shared\Traits\GroupByFilterTrait;
|
||||
use PandoraFMS\Modules\Shared\Traits\OrderFilterTrait;
|
||||
use PandoraFMS\Modules\Shared\Traits\PaginationFilterTrait;
|
||||
|
||||
abstract class FilterAbstract extends SerializableAbstract
|
||||
{
|
||||
use PaginationFilterTrait;
|
||||
use OrderFilterTrait;
|
||||
use GroupByFilterTrait;
|
||||
|
||||
public const ASC = 'ascending';
|
||||
public const DESC = 'descending';
|
||||
|
||||
private ?int $limit = null;
|
||||
|
||||
private ?int $offset = null;
|
||||
|
||||
private ?string $defaultFieldOrder = null;
|
||||
|
||||
private ?string $defaultDirectionOrder = null;
|
||||
|
||||
private ?array $fields = null;
|
||||
|
||||
private ?Entity $entityFilter = null;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// abstract public function getWhereClause(): string;
|
||||
abstract public function fieldsTranslate(): array;
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of fieldsFreeSearch.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getFieldsFreeSearch(): ?array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of multipleSearch.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getMultipleSearch(): ?array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of multipleSearchString.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getMultipleSearchString(): ?array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of fieldsFreeSearch.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getFieldAclGroupMysql(): ?string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of fieldsFreeSearch.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getModeAclGroupMysql(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function fromArray(array $params): static
|
||||
{
|
||||
$fails = $this->validate($params);
|
||||
if (empty($fails) === false) {
|
||||
throw new InvalidFilterException($fails);
|
||||
}
|
||||
|
||||
foreach ($params as $field => $value) {
|
||||
if (method_exists($this, 'set'.ucfirst($field)) === false) {
|
||||
if ($this->getEntityFilter() === null || method_exists($this->getEntityFilter(), 'set'.ucfirst($field)) === false) {
|
||||
throw new BadRequestException(__('Field').': '.$field.' '.__('is not a valid parameter'));
|
||||
}
|
||||
}
|
||||
|
||||
if (method_exists($this, 'set'.ucfirst($field)) === true) {
|
||||
$this->{'set'.ucfirst($field)}($value ?? null);
|
||||
} else if ($this->getEntityFilter() !== null && method_exists($this->getEntityFilter(), 'set'.ucfirst($field)) === true) {
|
||||
$this->getEntityFilter()->{'set'.ucfirst($field)}($value ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of limit.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getLimit(): ?int
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of limit.
|
||||
*
|
||||
* @param integer $limit
|
||||
*/
|
||||
public function setLimit(?int $limit): self
|
||||
{
|
||||
$this->limit = $limit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of offset.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getOffset(): ?int
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of offset.
|
||||
*
|
||||
* @param integer $offset
|
||||
*/
|
||||
public function setOffset(?int $offset): self
|
||||
{
|
||||
$this->offset = $offset;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of defaultFieldOrder.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getDefaultFieldOrder(): ?string
|
||||
{
|
||||
return $this->defaultFieldOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of defaultFieldOrder.
|
||||
*
|
||||
* @param string $defaultFieldOrder
|
||||
*/
|
||||
public function setDefaultFieldOrder(?string $defaultFieldOrder): self
|
||||
{
|
||||
$this->defaultFieldOrder = $defaultFieldOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of defaultDirectionOrder.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getDefaultDirectionOrder(): ?string
|
||||
{
|
||||
return $this->defaultDirectionOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of defaultDirectionOrder.
|
||||
*
|
||||
* @param string $defaultDirectionOrder
|
||||
*/
|
||||
public function setDefaultDirectionOrder(?string $defaultDirectionOrder): self
|
||||
{
|
||||
$this->defaultDirectionOrder = $defaultDirectionOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of entityFilter.
|
||||
*
|
||||
* @return ?Entity
|
||||
*/
|
||||
public function getEntityFilter(): ?Entity
|
||||
{
|
||||
return $this->entityFilter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of entityFilter.
|
||||
*
|
||||
* @param Entity $entityFilter
|
||||
*/
|
||||
public function setEntityFilter(?Entity $entityFilter): self
|
||||
{
|
||||
$this->entityFilter = $entityFilter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of fields.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getFields(): ?array
|
||||
{
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of fields.
|
||||
*
|
||||
* @param array $fields
|
||||
*/
|
||||
public function setFields(?array $fields): self
|
||||
{
|
||||
$this->fields = $fields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Core;
|
||||
|
||||
interface MappeableInterface
|
||||
{
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Core;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\InvalidFilterException;
|
||||
use JsonSerializable;
|
||||
|
||||
abstract class SerializableAbstract implements JsonSerializable
|
||||
{
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
abstract public function fieldsReadOnly(): array;
|
||||
|
||||
|
||||
abstract public function jsonSerialize(): mixed;
|
||||
|
||||
|
||||
abstract public function getValidations(): array;
|
||||
|
||||
|
||||
abstract public function validateFields(array $filters): array;
|
||||
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return $this->jsonSerialize();
|
||||
}
|
||||
|
||||
|
||||
public function validate(array $params): array
|
||||
{
|
||||
$filters = [];
|
||||
foreach ($this->getValidations() as $field => $type) {
|
||||
if (isset($params[$field]) === true) {
|
||||
$filters[$field] = [
|
||||
'type' => $type,
|
||||
'value' => ($params[$field] ?? ''),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->validateFields($filters);
|
||||
}
|
||||
|
||||
|
||||
public function fromArray(array $params): static
|
||||
{
|
||||
$fails = $this->validate($params);
|
||||
if (empty($fails) === false) {
|
||||
throw new InvalidFilterException($fails);
|
||||
}
|
||||
|
||||
foreach ($params as $field => $value) {
|
||||
// Not valid parameters.
|
||||
if (method_exists($this, 'set'.ucfirst($field)) === false) {
|
||||
throw new BadRequestException(__('Field').': '.$field.' '.__('is not a valid parameter'));
|
||||
}
|
||||
|
||||
// Read only parameters.
|
||||
if (isset($this->fieldsReadOnly()[$field]) === true) {
|
||||
throw new BadRequestException(__('Field').': '.$field.' '.__('is a read only parameter'));
|
||||
}
|
||||
|
||||
$this->{'set'.ucfirst($field)}($value ?? null);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Documentation;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Info(
|
||||
* title="Nueva API de Pandora FMS",
|
||||
* description="Nueva Api de pandora FMS",
|
||||
* termsOfService="https://example.com/terms/",
|
||||
* @OA\Contact(
|
||||
* name="Nombre del contacto",
|
||||
* url="https://www.example.com/support",
|
||||
* email="contacto@example.com"
|
||||
* ),
|
||||
* @OA\License(
|
||||
* name="Apache 2.0",
|
||||
* url="https://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
* ),
|
||||
* version="0.0.1"
|
||||
* ),
|
||||
* @OA\Schemes(
|
||||
* format="http"
|
||||
* ),
|
||||
* @OA\SecurityScheme(
|
||||
* securityScheme="bearerAuth",
|
||||
* in="header",
|
||||
* name="bearerAuth",
|
||||
* type="http",
|
||||
* scheme="bearer",
|
||||
* bearerFormat="pandoraBearer",
|
||||
* ),
|
||||
* @OA\Server(
|
||||
* url="/api/v1",
|
||||
* description="PandoraFMS API Server"
|
||||
* ),
|
||||
* @OA\Tag(
|
||||
* name="Users",
|
||||
* description="API Endpoints of users"
|
||||
* ),
|
||||
* @OA\OpenApi(
|
||||
* x={
|
||||
* "tagGroups"= {
|
||||
* {
|
||||
* "name"="Users",
|
||||
* "tags"={"Users"}
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* parameter="parameterPage",
|
||||
* name="page",
|
||||
* in="query",
|
||||
* description="page",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="integer",
|
||||
* default=0
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* parameter="parameterSizePage",
|
||||
* name="sizePage",
|
||||
* in="query",
|
||||
* description="Size page",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="integer",
|
||||
* default=0
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* parameter="parameterSortField",
|
||||
* name="sortField",
|
||||
* in="query",
|
||||
* description="sort field",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* default=""
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* parameter="parameterSortDirection",
|
||||
* name="sortDirection",
|
||||
* in="query",
|
||||
* description="sort direction",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* enum={
|
||||
* "ascending",
|
||||
* "descending"
|
||||
* },
|
||||
* default=""
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="BadRequest",
|
||||
* description="Bad request",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="object",
|
||||
* description="Error",
|
||||
* @OA\Property(
|
||||
* property="error",
|
||||
* type="string",
|
||||
* default="Message error"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="Unauthorized",
|
||||
* description="Unauthorized",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="object",
|
||||
* description="Error",
|
||||
* @OA\Property(
|
||||
* property="error",
|
||||
* type="string",
|
||||
* default="Message error"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="Forbidden",
|
||||
* description="Forbidden",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="object",
|
||||
* description="Error",
|
||||
* @OA\Property(
|
||||
* property="error",
|
||||
* type="string",
|
||||
* default="Message error"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="NotFound",
|
||||
* description="Not found",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="object",
|
||||
* description="Error",
|
||||
* @OA\Property(
|
||||
* property="error",
|
||||
* type="string",
|
||||
* default="Message error"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="InternalServerError",
|
||||
* description="Internal server error",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="object",
|
||||
* description="Error",
|
||||
* @OA\Property(
|
||||
* property="error",
|
||||
* type="string",
|
||||
* default="Message error"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="successfullyDeleted",
|
||||
* description="Successfully deleted",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="result",
|
||||
* type="string",
|
||||
* default="Successfully deleted"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="paginationData",
|
||||
* type="object",
|
||||
* description="Info pagination data",
|
||||
* @OA\Property(
|
||||
* property="totalPages",
|
||||
* type="integer",
|
||||
* nullable=true,
|
||||
* description="Number of pages",
|
||||
* readOnly=true
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="sizePage",
|
||||
* type="integer",
|
||||
* nullable=true,
|
||||
* description="Items per page",
|
||||
* readOnly=true
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="totalRegisters",
|
||||
* type="integer",
|
||||
* nullable=true,
|
||||
* description="Number of items",
|
||||
* readOnly=true
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="totalRegistersPage",
|
||||
* type="integer",
|
||||
* nullable=true,
|
||||
* description="Number of items this page",
|
||||
* readOnly=true
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="currentPage",
|
||||
* type="integer",
|
||||
* nullable=true,
|
||||
* description="Number of current page",
|
||||
* readOnly=true
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class OpenApi
|
||||
{
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Entities;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Core\MappeableInterface;
|
||||
use PandoraFMS\Modules\Shared\Core\SerializableAbstract;
|
||||
|
||||
abstract class Entity extends SerializableAbstract implements MappeableInterface
|
||||
{
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Entities;
|
||||
|
||||
use JsonSerializable;
|
||||
|
||||
class PaginationData implements JsonSerializable
|
||||
{
|
||||
|
||||
private ?int $totalPages = null;
|
||||
|
||||
private ?int $sizePage = null;
|
||||
|
||||
private ?int $currentPage = null;
|
||||
|
||||
private ?int $totalRegisters = null;
|
||||
|
||||
private ?int $totalRegistersPage = null;
|
||||
|
||||
private ?array $data = null;
|
||||
|
||||
|
||||
public function __construct(
|
||||
$currentPage,
|
||||
$sizePage,
|
||||
$totalRegisters,
|
||||
$data,
|
||||
) {
|
||||
$totalPages = empty($sizePage) === false ? ceil($totalRegisters / $sizePage) : 0;
|
||||
$this->setTotalPages($totalPages);
|
||||
$this->setSizePage($sizePage);
|
||||
$this->setCurrentPage($currentPage);
|
||||
$this->setSizePage($currentPage);
|
||||
$this->setTotalRegisters($totalRegisters);
|
||||
$this->setTotalRegistersPage(count($data));
|
||||
$this->setData($data);
|
||||
}
|
||||
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return $this->jsonSerialize();
|
||||
}
|
||||
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return [
|
||||
'paginationData' => [
|
||||
'totalPages' => $this->getTotalPages(),
|
||||
'sizePage' => $this->getSizePage(),
|
||||
'currentPage' => $this->getCurrentPage(),
|
||||
'totalRegisters' => $this->getTotalRegisters(),
|
||||
'totalRegistersPage' => $this->getTotalRegistersPage(),
|
||||
],
|
||||
'data' => $this->getData(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of totalPages.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getTotalPages(): ?int
|
||||
{
|
||||
return $this->totalPages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of totalPages.
|
||||
*
|
||||
* @param integer $totalPages
|
||||
*/
|
||||
public function setTotalPages(?int $totalPages): self
|
||||
{
|
||||
$this->totalPages = $totalPages;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of sizePage.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getSizePage(): ?int
|
||||
{
|
||||
return $this->sizePage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of sizePage.
|
||||
*
|
||||
* @param integer $sizePage
|
||||
*/
|
||||
public function setSizePage(?int $sizePage): self
|
||||
{
|
||||
$this->sizePage = $sizePage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of currentPage.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getCurrentPage(): ?int
|
||||
{
|
||||
return $this->currentPage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of currentPage.
|
||||
*
|
||||
* @param integer $currentPage
|
||||
*/
|
||||
public function setCurrentPage(?int $currentPage): self
|
||||
{
|
||||
$this->currentPage = $currentPage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of totalRegisters.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getTotalRegisters(): ?int
|
||||
{
|
||||
return $this->totalRegisters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of totalRegisters.
|
||||
*
|
||||
* @param integer $totalRegisters
|
||||
*/
|
||||
public function setTotalRegisters(?int $totalRegisters): self
|
||||
{
|
||||
$this->totalRegisters = $totalRegisters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of totalRegistersPage.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getTotalRegistersPage(): ?int
|
||||
{
|
||||
return $this->totalRegistersPage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of totalRegistersPage.
|
||||
*
|
||||
* @param integer $totalRegistersPage
|
||||
*/
|
||||
public function setTotalRegistersPage(?int $totalRegistersPage): self
|
||||
{
|
||||
$this->totalRegistersPage = $totalRegistersPage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of data.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getData(): ?array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of data.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(?array $data): self
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Enums;
|
||||
|
||||
enum HttpCodesEnum: int
|
||||
{
|
||||
public const CONTINUE = 100;
|
||||
public const SWITCHING_PROTOCOLS = 101;
|
||||
public const PROCESSING = 102;
|
||||
// RFC2518
|
||||
public const EARLY_HINTS = 103;
|
||||
// RFC8297
|
||||
public const OK = 200;
|
||||
public const CREATED = 201;
|
||||
public const ACCEPTED = 202;
|
||||
public const NON_AUTHORITATIVE_INFORMATION = 203;
|
||||
public const NO_CONTENT = 204;
|
||||
public const RESET_CONTENT = 205;
|
||||
public const PARTIAL_CONTENT = 206;
|
||||
public const MULTI_STATUS = 207;
|
||||
// RFC4918
|
||||
public const ALREADY_REPORTED = 208;
|
||||
// RFC5842
|
||||
public const IM_USED = 226;
|
||||
// RFC3229
|
||||
public const MULTIPLE_CHOICES = 300;
|
||||
public const MOVED_PERMANENTLY = 301;
|
||||
public const FOUND = 302;
|
||||
public const SEE_OTHER = 303;
|
||||
public const NOT_MODIFIED = 304;
|
||||
public const USE_PROXY = 305;
|
||||
public const RESERVED = 306;
|
||||
public const TEMPORARY_REDIRECT = 307;
|
||||
public const PERMANENTLY_REDIRECT = 308;
|
||||
// RFC7238
|
||||
public const BAD_REQUEST = 400;
|
||||
public const UNAUTHORIZED = 401;
|
||||
public const PAYMENT_REQUIRED = 402;
|
||||
public const FORBIDDEN = 403;
|
||||
public const NOT_FOUND = 404;
|
||||
public const METHOD_NOT_ALLOWED = 405;
|
||||
public const NOT_ACCEPTABLE = 406;
|
||||
public const PROXY_AUTHENTICATION_REQUIRED = 407;
|
||||
public const REQUEST_TIMEOUT = 408;
|
||||
public const CONFLICT = 409;
|
||||
public const GONE = 410;
|
||||
public const LENGTH_REQUIRED = 411;
|
||||
public const PRECONDITION_FAILED = 412;
|
||||
public const REQUEST_ENTITY_TOO_LARGE = 413;
|
||||
public const REQUEST_URI_TOO_LONG = 414;
|
||||
public const UNSUPPORTED_MEDIA_TYPE = 415;
|
||||
public const REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||
public const EXPECTATION_FAILED = 417;
|
||||
public const I_AM_A_TEAPOT = 418;
|
||||
// RFC2324
|
||||
public const MISDIRECTED_REQUEST = 421;
|
||||
// RFC7540
|
||||
public const UNPROCESSABLE_ENTITY = 422;
|
||||
// RFC4918
|
||||
public const LOCKED = 423;
|
||||
// RFC4918
|
||||
public const FAILED_DEPENDENCY = 424;
|
||||
// RFC4918
|
||||
public const TOO_EARLY = 425;
|
||||
// RFC-ietf-httpbis-replay-04
|
||||
public const UPGRADE_REQUIRED = 426;
|
||||
// RFC2817
|
||||
public const PRECONDITION_REQUIRED = 428;
|
||||
// RFC6585
|
||||
public const TOO_MANY_REQUESTS = 429;
|
||||
// RFC6585
|
||||
public const REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
|
||||
// RFC6585
|
||||
public const UNAVAILABLE_FOR_LEGAL_REASONS = 451;
|
||||
// RFC7725
|
||||
public const INTERNAL_SERVER_ERROR = 500;
|
||||
public const NOT_IMPLEMENTED = 501;
|
||||
public const BAD_GATEWAY = 502;
|
||||
public const SERVICE_UNAVAILABLE = 503;
|
||||
public const GATEWAY_TIMEOUT = 504;
|
||||
public const VERSION_NOT_SUPPORTED = 505;
|
||||
public const VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;
|
||||
// RFC2295
|
||||
public const INSUFFICIENT_STORAGE = 507;
|
||||
// RFC4918
|
||||
public const LOOP_DETECTED = 508;
|
||||
// RFC5842
|
||||
public const NOT_EXTENDED = 510;
|
||||
// RFC2774
|
||||
public const NETWORK_AUTHENTICATION_REQUIRED = 511;
|
||||
// RFC6585
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Enums;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Traits\EnumTrait;
|
||||
|
||||
enum LanguagesEnum: string
|
||||
{
|
||||
use EnumTrait;
|
||||
|
||||
case CATALONIAN = 'ca';
|
||||
case ENGLISH = 'en_GB';
|
||||
case SPANISH = 'es';
|
||||
case FRENCH = 'fr';
|
||||
case JAPANESE = 'ja';
|
||||
case RUSSIAN = 'ru';
|
||||
case CHINESE = 'zh_CN';
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
|
||||
class BadRequestException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public function __construct(string $fails)
|
||||
{
|
||||
parent::__construct($fails, HttpCodesEnum::BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
|
||||
class ForbiddenACLException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public function __construct(string $fails)
|
||||
{
|
||||
parent::__construct($fails, HttpCodesEnum::FORBIDDEN);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ForbiddenActionException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public function __construct(string $fails, int $httpCodesEnum)
|
||||
{
|
||||
parent::__construct($fails, $httpCodesEnum);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
|
||||
class InvalidClassException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public function __construct(string $fails)
|
||||
{
|
||||
parent::__construct($fails, HttpCodesEnum::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
|
||||
class InvalidFilterException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public function __construct(array $fails)
|
||||
{
|
||||
$str = '';
|
||||
foreach ($fails as $fail) {
|
||||
$str .= $fail['message'];
|
||||
}
|
||||
|
||||
parent::__construct(__($str), HttpCodesEnum::BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
|
||||
class NotFoundException extends Exception
|
||||
{
|
||||
|
||||
|
||||
public function __construct(string $fails)
|
||||
{
|
||||
parent::__construct($fails, HttpCodesEnum::NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Middlewares;
|
||||
|
||||
use PandoraFMS\Modules\Authentication\Services\GetUserTokenService;
|
||||
use PandoraFMS\Modules\Authentication\Services\UpdateTokenService;
|
||||
use PandoraFMS\Modules\Authentication\Services\ValidateUserTokenService;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\NotFoundException;
|
||||
use PandoraFMS\Modules\Shared\Services\Timestamp;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class UserTokenMiddleware
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private readonly ValidateUserTokenService $validateUserTokenService,
|
||||
private readonly GetUserTokenService $getUserTokenService,
|
||||
private readonly UpdateTokenService $updateTokenService,
|
||||
private readonly Timestamp $timestamp
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function check(Request $request): bool
|
||||
{
|
||||
global $config;
|
||||
$authorization = ($request->getHeader('Authorization')[0] ?? '');
|
||||
|
||||
/*
|
||||
@var ?Token $token
|
||||
*/
|
||||
try {
|
||||
$authorization = str_replace('Bearer ', '', $authorization);
|
||||
preg_match(
|
||||
'/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/',
|
||||
$authorization,
|
||||
$matches
|
||||
);
|
||||
|
||||
$uuid = ($matches[0] ?? '');
|
||||
$token = str_replace($uuid.'-', '', $authorization);
|
||||
$validToken = $this->validateUserTokenService->__invoke($uuid, $token);
|
||||
$token = $this->getUserTokenService->__invoke($uuid);
|
||||
if ($token !== null && $validToken) {
|
||||
$oldToken = clone $token;
|
||||
$token->setLastUsage($this->timestamp->getMysqlCurrentTimestamp(0));
|
||||
$this->updateTokenService->__invoke($token, $oldToken);
|
||||
}
|
||||
} catch (NotFoundException) {
|
||||
$token = null;
|
||||
}
|
||||
|
||||
if ($token !== null) {
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION['id_usuario'] = $token->getIdUser();
|
||||
$config['id_user'] = $token->getIdUser();
|
||||
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
session_write_close();
|
||||
}
|
||||
}
|
||||
|
||||
return $token !== null && $validToken;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Repositories;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Core\DataMapperAbstract;
|
||||
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
|
||||
use PandoraFMS\Modules\Shared\Entities\Entity;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\NotFoundException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
abstract class Repository
|
||||
{
|
||||
|
||||
|
||||
abstract protected function dbGetRow(
|
||||
string $field,
|
||||
string $table,
|
||||
mixed $value
|
||||
): array;
|
||||
|
||||
|
||||
abstract protected function dbGetValue(
|
||||
string $field,
|
||||
string $table,
|
||||
array $filters,
|
||||
string $whereJoin='AND'
|
||||
): mixed;
|
||||
|
||||
|
||||
abstract protected function dbGetValueSql(
|
||||
string $sql,
|
||||
?bool $cache=false
|
||||
): string;
|
||||
|
||||
|
||||
abstract protected function dbGetRowSql(
|
||||
string $sql
|
||||
): array;
|
||||
|
||||
|
||||
abstract protected function dbGetAllRowsSql(
|
||||
string $sql,
|
||||
?bool $cache=false
|
||||
): array;
|
||||
|
||||
|
||||
abstract protected function dbInsert(string $table, array $values): mixed;
|
||||
|
||||
|
||||
abstract protected function dbUpdate(string $table, array $values, array $condition): mixed;
|
||||
|
||||
|
||||
abstract protected function dbDelete(string $table, array $where): mixed;
|
||||
|
||||
|
||||
abstract protected function dbFormatWhereClauseSQL(array $values, $prefix=''): string;
|
||||
|
||||
|
||||
abstract public function buildQueryFilters(FilterAbstract $filter, DataMapperAbstract $mapper): string;
|
||||
|
||||
|
||||
abstract public function buildQueryPagination(FilterAbstract $filter): string;
|
||||
|
||||
|
||||
abstract public function buildQueryOrderBy(FilterAbstract $filter): string;
|
||||
|
||||
|
||||
abstract public function checkAclGroupMysql(string $field, ?string $mode=''): string;
|
||||
|
||||
|
||||
abstract public function buildQuery(
|
||||
FilterAbstract $filter,
|
||||
DataMapperAbstract $mapper,
|
||||
bool $count=false
|
||||
): string;
|
||||
|
||||
|
||||
abstract public function maxFieldSql(string $field): string;
|
||||
|
||||
|
||||
abstract public function safeInput(?string $value): ?string;
|
||||
|
||||
|
||||
abstract public function safeOutput(?string $value): ?string;
|
||||
|
||||
|
||||
/**
|
||||
* @return object[],
|
||||
*/
|
||||
public function __list(FilterAbstract $filter, DataMapperAbstract $mapper): array
|
||||
{
|
||||
try {
|
||||
$sql = $this->buildQuery($filter, $mapper);
|
||||
$list = $this->dbGetAllRowsSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if (is_array($list) === false) {
|
||||
throw new NotFoundException(__('%s not found', $mapper->getStringNameClass()));
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($list as $fields) {
|
||||
$result[] = $mapper->fromDatabase($fields);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function __rows(FilterAbstract $filter, DataMapperAbstract $mapper): array
|
||||
{
|
||||
try {
|
||||
$sql = $this->buildQuery($filter, $mapper);
|
||||
$rows = $this->dbGetAllRowsSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
|
||||
public function __count(FilterAbstract $filter, DataMapperAbstract $mapper): int
|
||||
{
|
||||
$sql = $this->buildQuery($filter, $mapper, true);
|
||||
try {
|
||||
$count = $this->dbGetValueSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return (int) $count;
|
||||
}
|
||||
|
||||
|
||||
public function __getOne(FilterAbstract $filter, DataMapperAbstract $mapper): object
|
||||
{
|
||||
try {
|
||||
$sql = $this->buildQuery($filter, $mapper);
|
||||
$result = $this->dbGetRowSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($result) === true) {
|
||||
throw new NotFoundException(__('%s not found', $mapper->getStringNameClass()));
|
||||
}
|
||||
|
||||
return $mapper->fromDatabase($result);
|
||||
}
|
||||
|
||||
|
||||
public function __create(Entity $entity, DataMapperAbstract $mapper): int
|
||||
{
|
||||
try {
|
||||
$id = $this->dbInsert(
|
||||
$mapper->getTableName(),
|
||||
$mapper->toDatabase($entity)
|
||||
);
|
||||
|
||||
// Create Relation.
|
||||
if (empty($mapper->getSearchFieldValueRelated()) === false) {
|
||||
$this->dbInsert(
|
||||
$mapper->getTableRelated(),
|
||||
[
|
||||
$mapper->getSearchFieldRelated() => $mapper->getSearchFieldValueRelated(),
|
||||
$mapper->getKeyRelated() => $id,
|
||||
]
|
||||
);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
|
||||
public function __update(Entity $entity, DataMapperAbstract $mapper, mixed $id): object
|
||||
{
|
||||
$values = $mapper->toDatabase($entity);
|
||||
unset($values[$mapper->getPrimaryKey()]);
|
||||
try {
|
||||
$this->dbUpdate(
|
||||
$mapper->getTableName(),
|
||||
$values,
|
||||
[$mapper->getPrimaryKey() => $id]
|
||||
);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
|
||||
public function __delete(
|
||||
mixed $id,
|
||||
DataMapperAbstract $mapper,
|
||||
?string $key=null,
|
||||
?array $where=null
|
||||
): void {
|
||||
try {
|
||||
if (empty($key) === true) {
|
||||
$key = $mapper->getPrimaryKey();
|
||||
}
|
||||
|
||||
$whereDelete = [$key => $id];
|
||||
if ($where !== null) {
|
||||
$whereDelete = array_merge($whereDelete, $where);
|
||||
}
|
||||
|
||||
$this->dbDelete($mapper->getTableName(), $whereDelete);
|
||||
|
||||
// Delete relation.
|
||||
if (empty($mapper->getTableRelated()) === false) {
|
||||
$this->dbDelete(
|
||||
$mapper->getTableRelated(),
|
||||
[
|
||||
$mapper->getSearchFieldRelated() => $mapper->getSearchFieldValueRelated(),
|
||||
$mapper->getKeyRelated() => $id,
|
||||
]
|
||||
);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function __getValue(FilterAbstract $filter, DataMapperAbstract $mapper): mixed
|
||||
{
|
||||
try {
|
||||
$sql = $this->buildQuery($filter, $mapper);
|
||||
$result = $this->dbGetValueSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function __maxField(string $field): string
|
||||
{
|
||||
return $this->maxFieldSql($field);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,484 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Repositories;
|
||||
|
||||
use Exception;
|
||||
use PandoraFMS\Modules\Shared\Core\DataMapperAbstract;
|
||||
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
|
||||
use PandoraFMS\Modules\Shared\Services\Config;
|
||||
|
||||
class RepositoryMySQL extends Repository
|
||||
{
|
||||
|
||||
|
||||
protected function dbGetRow(
|
||||
string $field,
|
||||
string $table,
|
||||
mixed $value
|
||||
): array {
|
||||
ob_start();
|
||||
$result = \db_get_row($table, $field, $value);
|
||||
$error = ob_get_clean();
|
||||
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = [];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbGetValue(
|
||||
string $field,
|
||||
string $table,
|
||||
array $filters,
|
||||
string $whereJoin='AND'
|
||||
): mixed {
|
||||
return \db_get_value_filter($field, $table, $filters, $whereJoin);
|
||||
}
|
||||
|
||||
|
||||
protected function dbGetValueSql(
|
||||
string $sql,
|
||||
?bool $cache=false
|
||||
): string {
|
||||
ob_start();
|
||||
$result = \db_get_value_sql($sql, $cache);
|
||||
$error = ob_get_clean();
|
||||
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = '';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbGetRowSql(
|
||||
string $sql
|
||||
): array {
|
||||
ob_start();
|
||||
$result = \db_get_row_sql($sql);
|
||||
$error = ob_get_clean();
|
||||
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = [];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbGetAllRowsSql(
|
||||
string $sql,
|
||||
?bool $cache=false
|
||||
): array {
|
||||
ob_start();
|
||||
$result = \db_get_all_rows_sql($sql, $cache);
|
||||
$error = ob_get_clean();
|
||||
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = [];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbInsert(string $table, array $values): mixed
|
||||
{
|
||||
ob_start();
|
||||
$result = \db_process_sql_insert($table, $values);
|
||||
$error = ob_get_clean();
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = [];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbUpdate(string $table, array $values, array $condition): mixed
|
||||
{
|
||||
ob_start();
|
||||
$result = \db_process_sql_update(
|
||||
$table,
|
||||
$values,
|
||||
$condition
|
||||
);
|
||||
$error = ob_get_clean();
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = [];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbDelete(string $table, array $where): mixed
|
||||
{
|
||||
ob_start();
|
||||
$result = \db_process_sql_delete($table, $where);
|
||||
|
||||
$error = ob_get_clean();
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$result = 0;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function dbFormatWhereClauseSQL(array $values, $prefix=''): string
|
||||
{
|
||||
ob_start();
|
||||
$result = \db_format_array_where_clause_sql($values, 'AND', $prefix);
|
||||
$error = ob_get_clean();
|
||||
if ($result === false && empty($error) === false) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function buildQueryFilters(FilterAbstract $filter, DataMapperAbstract $mapper): string
|
||||
{
|
||||
$where_clause = '1=1';
|
||||
|
||||
if ($filter->getEntityFilter() !== null) {
|
||||
$searchEntity = $mapper->toDatabase($filter->getEntityFilter());
|
||||
$searchEntity = array_filter($searchEntity, fn ($value) => !is_null($value) && $value !== '' && $value !== 'null');
|
||||
if (empty($searchEntity) === false) {
|
||||
$where_clause .= ' AND '.$this->dbFormatWhereClauseSQL($searchEntity, '`'.$mapper->getTableName().'`.');
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($filter->getFieldsFreeSearch()) === false
|
||||
&& empty($filter->toArray()['freeSearch']) === false
|
||||
) {
|
||||
$where_clause .= $this->freeSearch($filter->getFieldsFreeSearch(), $filter->toArray()['freeSearch']);
|
||||
}
|
||||
|
||||
if (empty($filter->getMultipleSearch()) === false) {
|
||||
$where_clause .= $this->multipleSearch($filter);
|
||||
}
|
||||
|
||||
if (empty($filter->getMultipleSearchString()) === false) {
|
||||
$where_clause .= $this->multipleSearchString($filter);
|
||||
}
|
||||
|
||||
if (empty($filter->getFieldAclGroupMysql()) === false) {
|
||||
$where_clause .= $this->checkAclGroupMysql(
|
||||
$filter->getFieldAclGroupMysql(),
|
||||
$filter->getModeAclGroupMysql()
|
||||
);
|
||||
}
|
||||
|
||||
return $where_clause;
|
||||
}
|
||||
|
||||
|
||||
private function freeSearch(array $fields, string $value): string
|
||||
{
|
||||
$clause = ' AND (';
|
||||
$count = count($fields);
|
||||
foreach ($fields as $field) {
|
||||
$clause .= sprintf('%s LIKE "%%%s%%"', $field, $value);
|
||||
|
||||
$count--;
|
||||
if ($count > 0) {
|
||||
$clause .= ' OR ';
|
||||
}
|
||||
}
|
||||
|
||||
$clause .= ') ';
|
||||
return $clause;
|
||||
}
|
||||
|
||||
|
||||
private function multipleSearch(FilterAbstract $filter): string
|
||||
{
|
||||
$fields = $filter->fieldsTranslate();
|
||||
$field = '';
|
||||
if (empty($fields) === false) {
|
||||
$field = ($fields[($filter->getMultipleSearch()['field'] ?? '')] ?? '');
|
||||
}
|
||||
|
||||
if (empty($field) === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$clause = ' AND '.$field.' IN ('.implode(',', $filter->getMultipleSearch()['data']).')';
|
||||
return $clause;
|
||||
}
|
||||
|
||||
|
||||
private function multipleSearchString(FilterAbstract $filter): string
|
||||
{
|
||||
$fields = $filter->fieldsTranslate();
|
||||
$field = '';
|
||||
if (empty($fields) === false) {
|
||||
$field = ($fields[($filter->getMultipleSearchString()['field'] ?? '')] ?? '');
|
||||
}
|
||||
|
||||
if (empty($field) === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$clause = ' AND '.$field.' IN ("'.implode('","', $filter->getMultipleSearchString()['data']).'")';
|
||||
return $clause;
|
||||
}
|
||||
|
||||
|
||||
public function buildQueryPagination(FilterAbstract $filter): string
|
||||
{
|
||||
$filter->setLimit($filter->getSizePage());
|
||||
$filter->setOffset($filter->getPage() * $filter->getSizePage());
|
||||
|
||||
$sqlLimit = '';
|
||||
if (empty($filter->getLimit()) === false) {
|
||||
$sqlLimit = sprintf(
|
||||
' LIMIT %d OFFSET %d',
|
||||
$filter->getLimit(),
|
||||
$filter->getOffset()
|
||||
);
|
||||
}
|
||||
|
||||
return $sqlLimit;
|
||||
}
|
||||
|
||||
|
||||
public function buildQueryOrderBy(FilterAbstract $filter): string
|
||||
{
|
||||
$default = '';
|
||||
if (empty($filter->getDefaultFieldOrder()) === false) {
|
||||
$default = sprintf(
|
||||
'ORDER BY %s %s',
|
||||
$filter->getDefaultFieldOrder(),
|
||||
$this->checkDirectionOrderByMsql($filter->getDefaultDirectionOrder())
|
||||
);
|
||||
}
|
||||
|
||||
$fieldsTranslate = $filter->fieldsTranslate();
|
||||
if (empty($fieldsTranslate) === true || isset($fieldsTranslate[$filter->getSortField()]) === false) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$field = $fieldsTranslate[$filter->getSortField()];
|
||||
$sort = 'ASC';
|
||||
if (empty($filter->getSortDirection()) === false) {
|
||||
$sort = $this->checkDirectionOrderByMsql($filter->getSortDirection());
|
||||
}
|
||||
|
||||
$return = '';
|
||||
if (empty($field) === false) {
|
||||
$return = 'ORDER BY '.$field.' '.$sort;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
public function buildQueryGroupBy(FilterAbstract $filter): string
|
||||
{
|
||||
$groupBy = '';
|
||||
$fieldsGroupByTranslate = [];
|
||||
if (empty($filter->getGroupByFields()) === false) {
|
||||
$fieldsTranslate = $filter->fieldsTranslate();
|
||||
if (empty($fieldsTranslate) === false) {
|
||||
foreach ($filter->getGroupByFields() as $value) {
|
||||
if (isset($fieldsTranslate[$value]) === false) {
|
||||
return $groupBy;
|
||||
}
|
||||
|
||||
$fieldsGroupByTranslate[] = $fieldsTranslate[$value];
|
||||
}
|
||||
|
||||
$groupBy = sprintf('GROUP BY %s', implode(',', $fieldsGroupByTranslate));
|
||||
}
|
||||
}
|
||||
|
||||
return $groupBy;
|
||||
}
|
||||
|
||||
|
||||
private function checkDirectionOrderByMsql(?string $direction): string
|
||||
{
|
||||
$directionArray = [
|
||||
'descending' => 'DESC',
|
||||
'ascending' => 'ASC',
|
||||
];
|
||||
|
||||
return (isset($directionArray[$direction]) === true) ? $directionArray[$direction] : 'ASC';
|
||||
}
|
||||
|
||||
|
||||
public function checkAclGroupMysql(string $field, ?string $mode=''): string
|
||||
{
|
||||
$config = new Config();
|
||||
$isAdmin = users_is_admin($config->get('id_user'));
|
||||
if ($isAdmin === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$userGroups = array_keys(
|
||||
\get_user_groups(
|
||||
$config->get('id_user'),
|
||||
'IM',
|
||||
true,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
if (empty($userGroups) === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($mode === 'array') {
|
||||
$filter = ' AND ( ';
|
||||
$i = 0;
|
||||
foreach ($userGroups as $group) {
|
||||
if ($i !== 0) {
|
||||
$filter .= ' OR ';
|
||||
}
|
||||
|
||||
$filter .= $group.' MEMBER OF ('.$field.') ';
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
$filter .= ' ) ';
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
$filter = sprintf(
|
||||
' AND %s IN (%s)',
|
||||
$field,
|
||||
implode(',', $userGroups)
|
||||
);
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
|
||||
public function buildQuery(
|
||||
FilterAbstract $filter,
|
||||
DataMapperAbstract $mapper,
|
||||
bool $count=false
|
||||
): string {
|
||||
$filters = $this->buildQueryFilters($filter, $mapper);
|
||||
if (empty($mapper->getSearchFieldRelated()) === false) {
|
||||
$filters .= sprintf(
|
||||
' AND %s.%s = %d',
|
||||
$mapper->getTableRelated(),
|
||||
$mapper->getSearchFieldRelated(),
|
||||
$mapper->getSearchFieldValueRelated()
|
||||
);
|
||||
}
|
||||
|
||||
$conditionInnerJoin = '';
|
||||
if (empty($mapper->getTableRelated()) === false) {
|
||||
$conditionInnerJoin = sprintf(
|
||||
'INNER JOIN %s ON %s.%s = %s.%s',
|
||||
$mapper->getTableRelated(),
|
||||
$mapper->getTableName(),
|
||||
$mapper->getPrimaryKey(),
|
||||
$mapper->getTableRelated(),
|
||||
$mapper->getKeyRelated()
|
||||
);
|
||||
}
|
||||
|
||||
$pagination = '';
|
||||
$orderBy = '';
|
||||
$groupBy = '';
|
||||
$fields = 'COUNT(*) as count';
|
||||
if ($count === false) {
|
||||
$pagination = $this->buildQueryPagination($filter);
|
||||
$orderBy = $this->buildQueryOrderBy($filter);
|
||||
$groupBy = $this->buildQueryGroupBy($filter);
|
||||
if (empty($filter->getFields()) === true) {
|
||||
$fields = $mapper->getTableName().'.*';
|
||||
} else {
|
||||
$buildFields = '';
|
||||
foreach ($filter->getFields() as $field) {
|
||||
if (empty($buildFields) === false) {
|
||||
$buildFields .= ' , ';
|
||||
}
|
||||
|
||||
$buildFields .= $field;
|
||||
}
|
||||
|
||||
$fields = $buildFields;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT %s
|
||||
FROM %s
|
||||
%s
|
||||
WHERE %s
|
||||
%s
|
||||
%s
|
||||
%s',
|
||||
$fields,
|
||||
$mapper->getTableName(),
|
||||
$conditionInnerJoin,
|
||||
$filters,
|
||||
$groupBy,
|
||||
$orderBy,
|
||||
$pagination
|
||||
);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
public function maxFieldSql(string $field): string
|
||||
{
|
||||
return 'MAX('.$field.')';
|
||||
}
|
||||
|
||||
|
||||
public function safeInput(?string $value): ?string
|
||||
{
|
||||
return \io_safe_input($value);
|
||||
}
|
||||
|
||||
|
||||
public function safeOutput(?string $value): ?string
|
||||
{
|
||||
return \io_safe_output($value);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Services;
|
||||
|
||||
class Audit
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Config $config,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function write(
|
||||
string $action,
|
||||
string $message='',
|
||||
string $extra=''
|
||||
): void {
|
||||
$idUser ??= $this->config->get('id_user');
|
||||
$remoteAddr ??= $this->config->get('REMOTE_ADDR');
|
||||
\db_pandora_audit(
|
||||
$action,
|
||||
__('User '.$idUser.': '.$message),
|
||||
$idUser,
|
||||
$remoteAddr,
|
||||
$extra
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Services;
|
||||
|
||||
final class Config
|
||||
{
|
||||
|
||||
|
||||
public function get(string $key, mixed $default=null): mixed
|
||||
{
|
||||
global $config;
|
||||
|
||||
return ($config[$key] ?? $default);
|
||||
}
|
||||
|
||||
|
||||
public function set(string $key, mixed $value): bool
|
||||
{
|
||||
global $config;
|
||||
// TODO: change.
|
||||
$res = \update_config_token($key, $value);
|
||||
if ($res === true) {
|
||||
$config[$key] = $value;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Services;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\ForbiddenActionException;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
class FileService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Config $config,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function moveUploadedFile(
|
||||
UploadedFileInterface $uploadedFile,
|
||||
?string $filename=null,
|
||||
?string $subdirectory=''
|
||||
) {
|
||||
$directory = $this->config->get('attachment_directory');
|
||||
$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
|
||||
|
||||
if ($filename === null) {
|
||||
$basename = bin2hex(random_bytes(8));
|
||||
$filename = sprintf('%s.%0.8s', $basename, $extension);
|
||||
}
|
||||
|
||||
$path = $directory.DIRECTORY_SEPARATOR;
|
||||
if (empty($subdirectory) === false) {
|
||||
$path .= $subdirectory.DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
$path .= $filename;
|
||||
|
||||
try {
|
||||
$uploadedFile->moveTo($path);
|
||||
} catch (\Throwable $th) {
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
$th->getCode() ? $th->getCode() : HttpCodesEnum::FORBIDDEN
|
||||
);
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
|
||||
public function removeFile(string $filename)
|
||||
{
|
||||
$directory = $this->config->get('attachment_directory');
|
||||
if (unlink($directory.DIRECTORY_SEPARATOR.$filename) === false) {
|
||||
throw new ForbiddenActionException(
|
||||
__('Error remove file'),
|
||||
HttpCodesEnum::FORBIDDEN
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function validationFile(
|
||||
UploadedFileInterface $file,
|
||||
string $regexInvalidExtension=null,
|
||||
int $maxSize=null
|
||||
): void {
|
||||
if (empty($regexInvalidExtension) === true) {
|
||||
$regexInvalidExtension = '/^(bat|exe|cmd|sh|php|php1|php2|php3|php4|php5|pl|cgi|386|dll|com|torrent|js|app|jar|iso|
|
||||
pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess|
|
||||
htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh)$/i';
|
||||
}
|
||||
|
||||
$extension = pathinfo($file->getClientFilename(), PATHINFO_EXTENSION);
|
||||
|
||||
if (preg_match($regexInvalidExtension, $extension)) {
|
||||
throw new BadRequestException(__('Error upload file, the file extension is not allowed'));
|
||||
}
|
||||
|
||||
if (empty($maxSize) === true) {
|
||||
$maxSize = $this->config->get('max_file_size');
|
||||
}
|
||||
|
||||
if ($file->getSize() > $this->calculateSizeBytes($maxSize)) {
|
||||
throw new BadRequestException(__('Error upload file, the file size exceeds the established limit'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function calculateSizeBytes(int $maxSize)
|
||||
{
|
||||
$max = ini_get('upload_max_filesize');
|
||||
if (empty($maxSize) === false && $maxSize < $max) {
|
||||
$max = $maxSize;
|
||||
}
|
||||
|
||||
return ($maxSize * 1000000);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Services;
|
||||
|
||||
class Timestamp
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Config $config
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function getMysqlCurrentTimestamp(
|
||||
int $unixtime,
|
||||
?string $format='Y-m-d H:i:s',
|
||||
): string {
|
||||
if ($unixtime == 0) {
|
||||
$unixtime = time();
|
||||
}
|
||||
|
||||
if (!is_numeric($unixtime)) {
|
||||
$unixtime = strtotime($unixtime);
|
||||
}
|
||||
|
||||
return date($format, $unixtime);
|
||||
}
|
||||
|
||||
|
||||
public function getMysqlSystemUtimestamp() : int
|
||||
{
|
||||
$return = \mysql_get_system_time();
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Services;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Exceptions\ForbiddenACLException;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Actions\GetUserProfileAction;
|
||||
|
||||
class ValidateAclSystem
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Config $config,
|
||||
private Audit $audit,
|
||||
private GetUserProfileAction $getUserProfileAction
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function validate(
|
||||
int $idGroup,
|
||||
string|array $permissions,
|
||||
string $message='',
|
||||
): void {
|
||||
// ACL.
|
||||
$idUser ??= $this->config->get('id_user');
|
||||
|
||||
$acl = false;
|
||||
if (is_array($permissions) === true) {
|
||||
foreach ($permissions as $permission) {
|
||||
if ((bool) \check_acl($idUser, $idGroup, $permission) === true) {
|
||||
$acl = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((bool) \check_acl($idUser, $idGroup, $permissions) === true) {
|
||||
$acl = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($acl === false) {
|
||||
$this->audit->write('ACL forbidden user does not have permission ', $message);
|
||||
throw new ForbiddenACLException('ACL forbidden user does not have permission '.$message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function validateUserGroups(
|
||||
int|array|null $idGroup,
|
||||
string $permissions,
|
||||
string $message='',
|
||||
): void {
|
||||
$idUser ??= $this->config->get('id_user');
|
||||
|
||||
$userGroups = \users_get_groups($idUser, $permissions, false, false);
|
||||
|
||||
$exist = true;
|
||||
if (is_array($idGroup) === true) {
|
||||
foreach ($idGroup as $group) {
|
||||
if (isset($userGroups[$group]) === false) {
|
||||
$exist = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($userGroups[$idGroup]) === false) {
|
||||
$exist = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($exist === false) {
|
||||
$this->audit->write('ACL Forbidden idGroup is not valid for this user', $message);
|
||||
throw new ForbiddenACLException('ACL Forbidden idGroup is not valid for this user');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function validateUserProfile(
|
||||
int $idProfile
|
||||
): void {
|
||||
$idUser ??= $this->config->get('id_user');
|
||||
$this->getUserProfileAction->__invoke($idUser, $idProfile);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Traits;
|
||||
|
||||
trait EnumTrait
|
||||
{
|
||||
|
||||
|
||||
public static function get(
|
||||
mixed $value,
|
||||
string $type='name'
|
||||
): mixed {
|
||||
$cases = static::cases();
|
||||
$index = array_search($value, array_column($cases, $type));
|
||||
if ($index !== false) {
|
||||
return $cases[$index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Traits;
|
||||
|
||||
trait GroupByFilterTrait
|
||||
{
|
||||
|
||||
private ?array $groupByFields = null;
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of groupByFields.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getGroupByFields(): ?array
|
||||
{
|
||||
return $this->groupByFields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of groupByFields.
|
||||
*
|
||||
* @param array $groupByFields
|
||||
*/
|
||||
public function setGroupByFields(?array $groupByFields): self
|
||||
{
|
||||
$this->groupByFields = $groupByFields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Traits;
|
||||
|
||||
trait OrderFilterTrait
|
||||
{
|
||||
|
||||
private ?string $sortField = null;
|
||||
|
||||
private ?string $sortDirection = null;
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of sortField.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getSortField(): ?string
|
||||
{
|
||||
return $this->sortField;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of sortField.
|
||||
*
|
||||
* @param string $sortField
|
||||
*/
|
||||
public function setSortField(?string $sortField): self
|
||||
{
|
||||
$this->sortField = $sortField;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of sortDirection.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getSortDirection(): ?string
|
||||
{
|
||||
return $this->sortDirection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of sortDirection.
|
||||
*
|
||||
* @param string $sortDirection
|
||||
*/
|
||||
public function setSortDirection(?string $sortDirection): self
|
||||
{
|
||||
$this->sortDirection = $sortDirection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Traits;
|
||||
|
||||
trait PaginationFilterTrait
|
||||
{
|
||||
|
||||
private ?int $sizePage = null;
|
||||
|
||||
private ?int $page = null;
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of sizePage.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getSizePage(): ?int
|
||||
{
|
||||
return $this->sizePage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of sizePage.
|
||||
*
|
||||
* @param integer $sizePage
|
||||
*/
|
||||
public function setSizePage(?int $sizePage): self
|
||||
{
|
||||
$this->sizePage = $sizePage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of page.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getPage(): ?int
|
||||
{
|
||||
return $this->page;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of page.
|
||||
*
|
||||
* @param integer $page
|
||||
*/
|
||||
public function setPage(?int $page): self
|
||||
{
|
||||
$this->page = $page;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Utils;
|
||||
|
||||
final class ArrayTools
|
||||
{
|
||||
|
||||
|
||||
public function extractFromObjectByAttribute(string $attribute, array $list): array
|
||||
{
|
||||
return array_reduce(
|
||||
$list,
|
||||
static function ($carry, $item) use ($attribute) {
|
||||
$carry[] = $item->{$attribute}();
|
||||
return $carry;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function indexObjectByAttribute(string $attribute, array $list): array
|
||||
{
|
||||
return array_reduce(
|
||||
$list,
|
||||
static function ($carry, $item) use ($attribute) {
|
||||
$carry[$item->{$attribute}()][] = $item;
|
||||
return $carry;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Shared\Validators;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Enums\LanguagesEnum;
|
||||
|
||||
class Validator
|
||||
{
|
||||
public const INTEGER = 'Integer';
|
||||
public const BOOLEAN = 'Bool';
|
||||
public const STRING = 'String';
|
||||
public const ARRAY = 'Array';
|
||||
public const GREATERTHAN = 'GreaterThan';
|
||||
public const GREATEREQUALTHAN = 'GreaterEqualThan';
|
||||
public const DATETIME = 'DateTime';
|
||||
public const TIMEZONE = 'TimeZone';
|
||||
public const LANGUAGE = 'Language';
|
||||
public const MAIL = 'Mail';
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function validate(array $args): array
|
||||
{
|
||||
$failed = [];
|
||||
foreach ($args as $field => $info) {
|
||||
$type = $info['type'];
|
||||
$value = $info['value'];
|
||||
|
||||
if (is_array($type) === true) {
|
||||
foreach ($type as $subType) {
|
||||
$result = $this->buildError($subType, $field, $value);
|
||||
if ($result) {
|
||||
$failed[$field] = $result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = $this->buildError($type, $field, $value);
|
||||
if ($result) {
|
||||
$failed[$field] = $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $failed;
|
||||
}
|
||||
|
||||
|
||||
private function buildError(string $type, string $field, $value): ?array
|
||||
{
|
||||
if ($this->{'is'.$type}($value) !== true) {
|
||||
return [
|
||||
'type' => 'integer',
|
||||
'message' => 'Field '.$field.' The value '.$value.' is not a valid '.$type.'.',
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function isInteger($arg): bool
|
||||
{
|
||||
return is_numeric($arg);
|
||||
}
|
||||
|
||||
|
||||
public function isGreaterThan($arg): bool
|
||||
{
|
||||
return $arg > 0;
|
||||
}
|
||||
|
||||
|
||||
public function isGreaterEqualThan($arg): bool
|
||||
{
|
||||
return $arg >= 0;
|
||||
}
|
||||
|
||||
|
||||
public function isBool($arg): bool
|
||||
{
|
||||
return is_bool($arg);
|
||||
}
|
||||
|
||||
|
||||
public function isString($arg): bool
|
||||
{
|
||||
return is_string($arg) || is_numeric($arg);
|
||||
}
|
||||
|
||||
|
||||
public function isArray($arg): bool
|
||||
{
|
||||
return is_array($arg);
|
||||
}
|
||||
|
||||
|
||||
public function isDateTime($date, $format='Y-m-d H:i:s')
|
||||
{
|
||||
$d = \DateTime::createFromFormat($format, $date);
|
||||
return $d && $d->format($format) == $date;
|
||||
}
|
||||
|
||||
|
||||
public function isTimeZone(string $timeZone): string
|
||||
{
|
||||
return array_search($timeZone, timezone_identifiers_list());
|
||||
}
|
||||
|
||||
|
||||
protected function isLanguage(string $language): bool
|
||||
{
|
||||
$result = LanguagesEnum::get(strtoupper($language));
|
||||
|
||||
return empty($result) === true ? false : true;
|
||||
}
|
||||
|
||||
|
||||
protected function isMail(string $mail): bool
|
||||
{
|
||||
return filter_var($mail, FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Services\CreateUserService;
|
||||
|
||||
final class CreateUserAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private CreateUserService $createUserService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(User $user): User
|
||||
{
|
||||
return $this->createUserService->__invoke($user);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Services\DeleteUserService;
|
||||
|
||||
final class DeleteUserAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private DeleteUserService $deleteUserService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(User $user): void
|
||||
{
|
||||
$this->deleteUserService->__invoke($user);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Services\GetUserService;
|
||||
|
||||
final class GetUserAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private GetUserService $getUserService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(string $idUser): User
|
||||
{
|
||||
return $this->getUserService->__invoke($idUser);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
use PandoraFMS\Modules\Users\Services\CountUserService;
|
||||
use PandoraFMS\Modules\Users\Services\ListUserService;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Entities\PaginationData;
|
||||
|
||||
final class ListUserAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private ListUserService $listUserService,
|
||||
private CountUserService $countUserService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserFilter $userFilter): array
|
||||
{
|
||||
return (new PaginationData(
|
||||
$userFilter->getPage(),
|
||||
$userFilter->getSizePage(),
|
||||
$this->countUserService->__invoke($userFilter),
|
||||
$this->listUserService->__invoke($userFilter)
|
||||
))->toArray();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Services\UpdateUserService;
|
||||
|
||||
final class UpdateUserAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UpdateUserService $updateUserService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(User $user, User $oldUser): User
|
||||
{
|
||||
return $this->updateUserService->__invoke($user, $oldUser);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Users\Actions\CreateUserAction;
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
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 CreateUserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private CreateUserAction $createUserAction,
|
||||
private ValidateAclSystem $acl,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* tags={"Users"},
|
||||
* path="/user",
|
||||
* summary="Creates a new users",
|
||||
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyUser"),
|
||||
* @OA\Response(response=200, ref="#/components/responses/ResponseUser"),
|
||||
* @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 User $user.
|
||||
$user = $this->fromRequest($request, User::class);
|
||||
|
||||
$this->acl->validate(0, 'UM', ' tried to manage user');
|
||||
|
||||
$result = $this->createUserAction->__invoke($user);
|
||||
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Users\Actions\DeleteUserAction;
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
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 DeleteUserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private DeleteUserAction $deleteUserAction,
|
||||
private ValidateAclSystem $acl,
|
||||
private GetUserAction $getUserAction
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Delete(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* tags={"Users"},
|
||||
* path="/user/{id}",
|
||||
* summary="Deletes an user object.",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @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
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$user = $this->getUserAction->__invoke($idUser);
|
||||
|
||||
$this->acl->validate(0, 'UM', ' tried to manage user');
|
||||
|
||||
$result = $this->deleteUserAction->__invoke($user);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
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 GetUserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private GetUserAction $getUserAction,
|
||||
private ValidateAclSystem $acl
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* path="/user/{id}",
|
||||
* tags={"Users"},
|
||||
* summary="show users",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @OA\Response(response=200, ref="#/components/responses/ResponseUser"),
|
||||
* @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
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$result = $this->getUserAction->__invoke($idUser);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Users\Actions\ListUserAction;
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
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 ListUserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private ListUserAction $listUserAction,
|
||||
private ValidateAclSystem $acl,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* tags={"Users"},
|
||||
* path="/user/list",
|
||||
* summary="List user",
|
||||
* @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/requestBodyUserFilter"),
|
||||
* @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/User",
|
||||
* description="Array of user 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 UserFilter $userFilter.
|
||||
$userFilter = $this->fromRequest($request, UserFilter::class);
|
||||
|
||||
$result = $this->listUserAction->__invoke($userFilter);
|
||||
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
use PandoraFMS\Modules\Users\Actions\UpdateUserAction;
|
||||
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="/user/{id}",
|
||||
* tags={"Users"},
|
||||
* summary="Updates an user",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyUser"),
|
||||
* @OA\Response(response=200, ref="#/components/responses/ResponseUser"),
|
||||
* @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 UpdateUserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UpdateUserAction $updateUserAction,
|
||||
private ValidateAclSystem $acl,
|
||||
private GetUserAction $getUserAction
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(Request $request, Response $response): Response
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$user = $this->getUserAction->__invoke($idUser);
|
||||
|
||||
$oldUser = clone $user;
|
||||
$params = $this->extractParams($request);
|
||||
$user->fromArray($params);
|
||||
|
||||
$this->acl->validate(0, 'UM', ' tried to manage user');
|
||||
|
||||
$result = $this->updateUserAction->__invoke($user, $oldUser);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
2185
pandora_console/include/lib/Modules/Users/Entities/User.php
Normal file
2185
pandora_console/include/lib/Modules/Users/Entities/User.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Entities;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Builders\Builder;
|
||||
use PandoraFMS\Modules\Shared\Core\DataMapperAbstract;
|
||||
use PandoraFMS\Modules\Shared\Core\MappeableInterface;
|
||||
use PandoraFMS\Modules\Shared\Enums\LanguagesEnum;
|
||||
use PandoraFMS\Modules\Shared\Repositories\Repository;
|
||||
use PandoraFMS\Modules\Users\Enums\UserHomeScreenEnum;
|
||||
use PandoraFMS\Modules\Users\Enums\UserMetaconsoleAccessEnum;
|
||||
|
||||
final class UserDataMapper extends DataMapperAbstract
|
||||
{
|
||||
public const TABLE_NAME = 'tusuario';
|
||||
public const ID_USER = 'id_user';
|
||||
public const FULLNAME = 'fullname';
|
||||
public const FIRSTNAME = 'firstname';
|
||||
public const LASTNAME = 'lastname';
|
||||
public const MIDDLENAME = 'middlename';
|
||||
public const PASSWORD = 'password';
|
||||
public const COMMENTS = 'comments';
|
||||
public const LAST_CONNECT = 'last_connect';
|
||||
public const REGISTERED = 'registered';
|
||||
public const EMAIL = 'email';
|
||||
public const PHONE = 'phone';
|
||||
public const IS_ADMIN = 'is_admin';
|
||||
public const LANGUAGE = 'language';
|
||||
public const TIMEZONE = 'timezone';
|
||||
public const BLOCK_SIZE = 'block_size';
|
||||
public const ID_SKIN = 'id_skin';
|
||||
public const DISABLED = 'disabled';
|
||||
public const SHORTCUT = 'shortcut';
|
||||
public const SHORTCUT_DATA = 'shortcut_data';
|
||||
public const SECTION = 'section';
|
||||
public const DATA_SECTION = 'data_section';
|
||||
public const METACONSOLE_SECTION = 'metaconsole_section';
|
||||
public const METACONSOLE_DATA_SECTION = 'metaconsole_data_section';
|
||||
public const FORCE_CHANGE_PASS = 'force_change_pass';
|
||||
public const LAST_PASS_CHANGE = 'last_pass_change';
|
||||
public const LAST_FAILED_LOGIN = 'last_failed_login';
|
||||
public const FAILED_ATTEMPT = 'failed_attempt';
|
||||
public const LOGIN_BLOCKED = 'login_blocked';
|
||||
public const METACONSOLE_ACCESS = 'metaconsole_access';
|
||||
public const NOT_LOGIN = 'not_login';
|
||||
public const LOCAL_USER = 'local_user';
|
||||
public const METACONSOLE_AGENTS_MANAGER = 'metaconsole_agents_manager';
|
||||
public const METACONSOLE_ACCESS_NODE = 'metaconsole_access_node';
|
||||
public const STRICT_ACL = 'strict_acl';
|
||||
public const ID_FILTER = 'id_filter';
|
||||
public const SESSION_TIME = 'session_time';
|
||||
public const DEFAULT_EVENT_FILTER = 'default_event_filter';
|
||||
public const METACONSOLE_DEFAULT_EVENT_FILTER = 'metaconsole_default_event_filter';
|
||||
public const SHOW_TIPS_STARTUP = 'show_tips_startup';
|
||||
public const AUTOREFRESH_WHITE_LIST = 'autorefresh_white_list';
|
||||
public const TIME_AUTOREFRESH = 'time_autorefresh';
|
||||
public const DEFAULT_CUSTOM_VIEW = 'default_custom_view';
|
||||
public const EHORUS_USER_LEVEL_USER = 'ehorus_user_level_user';
|
||||
public const EHORUS_USER_LEVEL_PASS = 'ehorus_user_level_pass';
|
||||
public const EHORUS_USER_LEVEL_ENABLED = 'ehorus_user_level_enabled';
|
||||
public const INTEGRIA_USER_LEVEL_USER = 'integria_user_level_user';
|
||||
public const INTEGRIA_USER_LEVEL_PASS = 'integria_user_level_pass';
|
||||
public const API_TOKEN = 'api_token';
|
||||
public const ALLOWED_IP_ACTIVE = 'allowed_ip_active';
|
||||
public const ALLOWED_IP_LIST = 'allowed_ip_list';
|
||||
public const AUTH_TOKEN_SECRET = 'auth_token_secret';
|
||||
public const SESSION_MAX_TIME_EXPIRE = 'session_max_time_expire';
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Repository $repository,
|
||||
private Builder $builder,
|
||||
) {
|
||||
parent::__construct(
|
||||
self::TABLE_NAME,
|
||||
self::ID_USER,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return User::class;
|
||||
}
|
||||
|
||||
|
||||
public function fromDatabase(array $data): User
|
||||
{
|
||||
return $this->builder->build(
|
||||
new User(),
|
||||
[
|
||||
'idUser' => $data[self::ID_USER],
|
||||
'fullName' => $this->repository->safeOutput($data[self::FULLNAME]),
|
||||
'firstName' => $this->repository->safeOutput($data[self::FIRSTNAME]),
|
||||
'lastName' => $this->repository->safeOutput($data[self::LASTNAME]),
|
||||
'middleName' => $this->repository->safeOutput($data[self::MIDDLENAME]),
|
||||
'password' => $data[self::PASSWORD],
|
||||
'comments' => $this->repository->safeOutput($data[self::COMMENTS]),
|
||||
'lastConnect' => $data[self::LAST_CONNECT],
|
||||
'registered' => $data[self::REGISTERED],
|
||||
'email' => $this->repository->safeOutput($data[self::EMAIL]),
|
||||
'phone' => $this->repository->safeOutput($data[self::PHONE]),
|
||||
'isAdmin' => $data[self::IS_ADMIN],
|
||||
'language' => LanguagesEnum::get($data[self::LANGUAGE]),
|
||||
'timezone' => $data[self::TIMEZONE],
|
||||
'blockSize' => $data[self::BLOCK_SIZE],
|
||||
'idSkin' => $data[self::ID_SKIN],
|
||||
'disabled' => $data[self::DISABLED],
|
||||
'shortcut' => $data[self::SHORTCUT],
|
||||
'shortcutData' => $this->repository->safeOutput($data[self::SHORTCUT_DATA]),
|
||||
'section' => UserHomeScreenEnum::get($data[self::SECTION]),
|
||||
'dataSection' => $this->repository->safeOutput($data[self::DATA_SECTION]),
|
||||
'metaconsoleSection' => UserHomeScreenEnum::get($data[self::METACONSOLE_SECTION]),
|
||||
'metaconsoleDataSection' => $this->repository->safeOutput($data[self::METACONSOLE_DATA_SECTION]),
|
||||
'forceChangePass' => $data[self::FORCE_CHANGE_PASS],
|
||||
'lastPassChange' => $data[self::LAST_PASS_CHANGE],
|
||||
'lastFailedLogin' => $data[self::LAST_FAILED_LOGIN],
|
||||
'failedAttempt' => $data[self::FAILED_ATTEMPT],
|
||||
'loginBlocked' => $data[self::LOGIN_BLOCKED],
|
||||
'metaconsoleAccess' => UserMetaconsoleAccessEnum::get($data[self::METACONSOLE_ACCESS]),
|
||||
'notLogin' => $data[self::NOT_LOGIN],
|
||||
'localUser' => $data[self::LOCAL_USER],
|
||||
'metaconsoleAgentsManager' => $data[self::METACONSOLE_AGENTS_MANAGER],
|
||||
'metaconsoleAccessNode' => $data[self::METACONSOLE_ACCESS_NODE],
|
||||
'strictAcl' => $data[self::STRICT_ACL],
|
||||
'idFilter' => $data[self::ID_FILTER],
|
||||
'sessionTime' => $data[self::SESSION_TIME],
|
||||
'defaultEventFilter' => $data[self::DEFAULT_EVENT_FILTER],
|
||||
'metaconsoleDefaultEventFilter' => $data[self::METACONSOLE_DEFAULT_EVENT_FILTER],
|
||||
'showTipsStartup' => $data[self::SHOW_TIPS_STARTUP],
|
||||
'autorefreshWhiteList' => json_decode($this->repository->safeOutput($data[self::AUTOREFRESH_WHITE_LIST])),
|
||||
'timeAutorefresh' => $data[self::TIME_AUTOREFRESH],
|
||||
'defaultCustomView' => $data[self::DEFAULT_CUSTOM_VIEW],
|
||||
'ehorusUserLevelUser' => $this->repository->safeOutput($data[self::EHORUS_USER_LEVEL_USER]),
|
||||
'ehorusUserLevelPass' => $this->repository->safeOutput($data[self::EHORUS_USER_LEVEL_PASS]),
|
||||
'ehorusUserLevelEnabled' => $data[self::EHORUS_USER_LEVEL_ENABLED],
|
||||
'itsmUserLevelUser' => $this->repository->safeOutput($data[self::INTEGRIA_USER_LEVEL_USER]),
|
||||
'itsmUserLevelPass' => $this->repository->safeOutput($data[self::INTEGRIA_USER_LEVEL_PASS]),
|
||||
'apiToken' => $data[self::API_TOKEN],
|
||||
'allowedIpActive' => $data[self::ALLOWED_IP_ACTIVE],
|
||||
'allowedIpList' => $this->repository->safeOutput($data[self::ALLOWED_IP_LIST]),
|
||||
'authTokenSecret' => $data[self::AUTH_TOKEN_SECRET],
|
||||
'sessionMaxTimeExpire' => $data[self::SESSION_MAX_TIME_EXPIRE],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function toDatabase(MappeableInterface $data): array
|
||||
{
|
||||
/*
|
||||
@var User $data
|
||||
*/
|
||||
return [
|
||||
self::ID_USER => $data->getIdUser(),
|
||||
self::FULLNAME => $this->repository->safeInput($data->getFullName()),
|
||||
self::FIRSTNAME => $this->repository->safeInput($data->getFirstName()),
|
||||
self::LASTNAME => $this->repository->safeInput($data->getLastName()),
|
||||
self::MIDDLENAME => $this->repository->safeInput($data->getMiddleName()),
|
||||
self::PASSWORD => $data->getPassword(),
|
||||
self::COMMENTS => $this->repository->safeInput($data->getComments()),
|
||||
self::LAST_CONNECT => $data->getLastConnect(),
|
||||
self::REGISTERED => $data->getRegistered(),
|
||||
self::EMAIL => $this->repository->safeInput($data->getEmail()),
|
||||
self::PHONE => $this->repository->safeInput($data->getPhone()),
|
||||
self::IS_ADMIN => $data->getIsAdmin(),
|
||||
self::LANGUAGE => $data->getLanguage()?->value,
|
||||
self::TIMEZONE => $data->getTimezone(),
|
||||
self::BLOCK_SIZE => $data->getBlockSize(),
|
||||
self::ID_SKIN => $data->getIdSkin(),
|
||||
self::DISABLED => $data->getDisabled(),
|
||||
self::SHORTCUT => $data->getShortcut(),
|
||||
self::SHORTCUT_DATA => $this->repository->safeInput($data->getShortcutData()),
|
||||
self::SECTION => $data->getSection()?->value,
|
||||
self::DATA_SECTION => $this->repository->safeInput($data->getDataSection()),
|
||||
self::METACONSOLE_SECTION => $data->getMetaconsoleSection()?->value,
|
||||
self::METACONSOLE_DATA_SECTION => $this->repository->safeInput($data->getMetaconsoleDataSection()),
|
||||
self::FORCE_CHANGE_PASS => $data->getForceChangePass(),
|
||||
self::LAST_PASS_CHANGE => $data->getLastPassChange(),
|
||||
self::LAST_FAILED_LOGIN => $data->getLastFailedLogin(),
|
||||
self::FAILED_ATTEMPT => $data->getFailedAttempt(),
|
||||
self::LOGIN_BLOCKED => $data->getLoginBlocked(),
|
||||
self::METACONSOLE_ACCESS => $data->getMetaconsoleAccess()?->value,
|
||||
self::NOT_LOGIN => $data->getNotLogin(),
|
||||
self::LOCAL_USER => $data->getLocalUser(),
|
||||
self::METACONSOLE_AGENTS_MANAGER => $data->getMetaconsoleAgentsManager(),
|
||||
self::METACONSOLE_ACCESS_NODE => $data->getMetaconsoleAccessNode(),
|
||||
self::STRICT_ACL => $data->getStrictAcl(),
|
||||
self::ID_FILTER => $data->getIdFilter(),
|
||||
self::SESSION_TIME => $data->getSessionTime(),
|
||||
self::DEFAULT_EVENT_FILTER => $data->getDefaultEventFilter(),
|
||||
self::METACONSOLE_DEFAULT_EVENT_FILTER => $data->getMetaconsoleDefaultEventFilter(),
|
||||
self::SHOW_TIPS_STARTUP => $data->getShowTipsStartup(),
|
||||
self::AUTOREFRESH_WHITE_LIST => $this->repository->safeInput(json_encode($data->getAutorefreshWhiteList())),
|
||||
self::TIME_AUTOREFRESH => $data->getTimeAutorefresh(),
|
||||
self::DEFAULT_CUSTOM_VIEW => $data->getDefaultCustomView(),
|
||||
self::EHORUS_USER_LEVEL_USER => $this->repository->safeInput($data->getEhorusUserLevelUser()),
|
||||
self::EHORUS_USER_LEVEL_PASS => $this->repository->safeInput($data->getEhorusUserLevelPass()),
|
||||
self::EHORUS_USER_LEVEL_ENABLED => $data->getEhorusUserLevelEnabled(),
|
||||
self::INTEGRIA_USER_LEVEL_USER => $this->repository->safeInput($data->getItsmUserLevelUser()),
|
||||
self::INTEGRIA_USER_LEVEL_PASS => $this->repository->safeInput($data->getItsmUserLevelPass()),
|
||||
self::API_TOKEN => $data->getApiToken(),
|
||||
self::ALLOWED_IP_ACTIVE => $data->getAllowedIpActive(),
|
||||
self::ALLOWED_IP_LIST => $this->repository->safeInput($data->getAllowedIpList()),
|
||||
self::AUTH_TOKEN_SECRET => $data->getAuthTokenSecret(),
|
||||
self::SESSION_MAX_TIME_EXPIRE => $data->getSessionMaxTimeExpire(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Entities;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
|
||||
use PandoraFMS\Modules\Users\Validators\UserValidator;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="UserFilter",
|
||||
* type="object",
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/User"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="freeSearch",
|
||||
* type="string",
|
||||
* nullable=true,
|
||||
* default=null,
|
||||
* description="Find word in fullname and comments fields."
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="multipleSearchString",
|
||||
* type="string",
|
||||
* nullable=true,
|
||||
* default=null,
|
||||
* description="search string in field."
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\RequestBody(
|
||||
* request="requestBodyUserFilter",
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(ref="#/components/schemas/UserFilter")
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
final class UserFilter extends FilterAbstract
|
||||
{
|
||||
|
||||
private ?string $freeSearch = null;
|
||||
|
||||
private ?array $multipleSearchString = null;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setDefaultFieldOrder(UserDataMapper::ID_USER);
|
||||
$this->setDefaultDirectionOrder($this::ASC);
|
||||
$this->setEntityFilter(new User());
|
||||
}
|
||||
|
||||
|
||||
public function fieldsTranslate(): array
|
||||
{
|
||||
return [
|
||||
'idUser' => UserDataMapper::TABLE_NAME.'.'.UserDataMapper::ID_USER,
|
||||
'fullName' => UserDataMapper::TABLE_NAME.'.'.UserDataMapper::FULLNAME,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function fieldsReadOnly(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return [
|
||||
'freeSearch' => $this->getFreeSearch(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getValidations(): array
|
||||
{
|
||||
$validations = [];
|
||||
if ($this->getEntityFilter() !== null) {
|
||||
$validations = $this->getEntityFilter()->getValidations();
|
||||
}
|
||||
|
||||
$validations['freeSearch'] = UserValidator::STRING;
|
||||
return $validations;
|
||||
}
|
||||
|
||||
|
||||
public function validateFields(array $filters): array
|
||||
{
|
||||
return (new UserValidator())->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 [
|
||||
UserDataMapper::TABLE_NAME.'.'.UserDataMapper::FULLNAME,
|
||||
UserDataMapper::TABLE_NAME.'.'.UserDataMapper::ID_USER,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of multipleSearchString.
|
||||
*
|
||||
* @return ?array
|
||||
*/
|
||||
public function getMultipleSearchString(): ?array
|
||||
{
|
||||
return $this->multipleSearchString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of multipleSearchString.
|
||||
*
|
||||
* @param array $multipleSearchString
|
||||
*/
|
||||
public function setMultipleSearchString(?array $multipleSearchString): self
|
||||
{
|
||||
$this->multipleSearchString = $multipleSearchString;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Enums;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Traits\EnumTrait;
|
||||
|
||||
enum UserHomeScreenEnum: string
|
||||
{
|
||||
use EnumTrait;
|
||||
|
||||
case default = 'default';
|
||||
case VISUAL_CONSOLE = 'visual_console';
|
||||
case EVENT_LIST = 'event_list';
|
||||
case GROUP_VIEW = 'group_view';
|
||||
case TACTICAL_VIEW = 'tactical_view';
|
||||
case ALERT_DETAIL = 'alert_detail';
|
||||
case EXTERNAL_LINK = 'external_link';
|
||||
case OTHER = 'other';
|
||||
case DASHBOARD = 'dashboard';
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Enums;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Traits\EnumTrait;
|
||||
|
||||
enum UserMetaconsoleAccessEnum: string
|
||||
{
|
||||
use EnumTrait;
|
||||
|
||||
case BASIC = 'basic';
|
||||
case ADVANCED = 'advanced';
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Repositories;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
|
||||
interface UserRepository
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return User[],
|
||||
*/
|
||||
public function list(UserFilter $userFilter): array;
|
||||
|
||||
|
||||
public function count(UserFilter $userFilter): int;
|
||||
|
||||
|
||||
public function getOne(UserFilter $userFilter): User;
|
||||
|
||||
|
||||
public function create(User $user): User;
|
||||
|
||||
|
||||
public function update(User $user): User;
|
||||
|
||||
|
||||
public function delete(string $id): void;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Repositories;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Core\DataMapperAbstract;
|
||||
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
|
||||
use PandoraFMS\Modules\Shared\Enums\HttpCodesEnum;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\NotFoundException;
|
||||
use PandoraFMS\Modules\Shared\Repositories\RepositoryMySQL;
|
||||
use PandoraFMS\Modules\Shared\Services\Config;
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Entities\UserDataMapper;
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
use PandoraFMS\Modules\Users\Enums\UserLevelEnum;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class UserRepositoryMySQL extends RepositoryMySQL implements UserRepository
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UserDataMapper $userDataMapper
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return User[],
|
||||
*/
|
||||
public function list(UserFilter $userFilter): array
|
||||
{
|
||||
try {
|
||||
$sql = $this->getUsersQuery($userFilter, $this->userDataMapper);
|
||||
$list = $this->dbGetAllRowsSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if (is_array($list) === false) {
|
||||
throw new NotFoundException(__('%s not found', $this->userDataMapper->getStringNameClass()));
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($list as $fields) {
|
||||
$result[] = $this->userDataMapper->fromDatabase($fields);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function count(UserFilter $userFilter): int
|
||||
{
|
||||
$sql = $this->getUsersQuery($userFilter, $this->userDataMapper, true);
|
||||
try {
|
||||
hd($sql, true);
|
||||
$count = $this->dbGetValueSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return (int) $count;
|
||||
}
|
||||
|
||||
|
||||
public function getOne(UserFilter $userFilter): User
|
||||
{
|
||||
try {
|
||||
$sql = $this->getUsersQuery($userFilter, $this->userDataMapper);
|
||||
$result = $this->dbGetRowSql($sql);
|
||||
} catch (\Throwable $th) {
|
||||
// Capture errors mysql.
|
||||
throw new InvalidArgumentException(
|
||||
strip_tags($th->getMessage()),
|
||||
HttpCodesEnum::INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($result) === true) {
|
||||
throw new NotFoundException(__('%s not found', $this->userDataMapper->getStringNameClass()));
|
||||
}
|
||||
|
||||
return $this->userDataMapper->fromDatabase($result);
|
||||
}
|
||||
|
||||
|
||||
public function create(User $user): User
|
||||
{
|
||||
$this->__create($user, $this->userDataMapper);
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
public function update(User $user): User
|
||||
{
|
||||
return $this->__update(
|
||||
$user,
|
||||
$this->userDataMapper,
|
||||
$user->getIdUser()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function delete(string $id): void
|
||||
{
|
||||
$this->__delete($id, $this->userDataMapper);
|
||||
}
|
||||
|
||||
|
||||
private function getUsersQuery(
|
||||
FilterAbstract $filter,
|
||||
DataMapperAbstract $mapper,
|
||||
bool $count=false
|
||||
): string {
|
||||
$pagination = '';
|
||||
$orderBy = '';
|
||||
$fields = 'COUNT(DISTINCT tusuario.id_user) as count';
|
||||
$filters = $this->buildQueryFilters($filter, $mapper);
|
||||
|
||||
if ($count === false) {
|
||||
$pagination = $this->buildQueryPagination($filter);
|
||||
$orderBy = $this->buildQueryOrderBy($filter);
|
||||
if (empty($filter->getFields()) === true) {
|
||||
$fields = 'DISTINCT tusuario.*';
|
||||
} else {
|
||||
$buildFields = '';
|
||||
foreach ($filter->getFields() as $field) {
|
||||
if (empty($buildFields) === false) {
|
||||
$buildFields .= ' , ';
|
||||
}
|
||||
|
||||
$buildFields .= $field;
|
||||
}
|
||||
|
||||
$fields = $buildFields;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT %s
|
||||
FROM tusuario
|
||||
LEFT JOIN tusuario_perfil
|
||||
ON tusuario.id_user = tusuario_perfil.id_usuario
|
||||
WHERE %s
|
||||
%s
|
||||
%s',
|
||||
$fields,
|
||||
$filters,
|
||||
$orderBy,
|
||||
$pagination
|
||||
);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\NotFoundException;
|
||||
use PandoraFMS\Modules\Shared\Repositories\Repository;
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Entities\UserDataMapper;
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
|
||||
final class CheckOldPasswordUserService
|
||||
{
|
||||
public function __construct(
|
||||
private Repository $repository,
|
||||
private UserDataMapper $userDataMapper
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(User $user): void
|
||||
{
|
||||
$userFilter = new UserFilter();
|
||||
$userFilter->setIdUser($user->getIdUser());
|
||||
$userFilter->setPassword($user->getOldPassword());
|
||||
try {
|
||||
$this->repository->__getOne(
|
||||
$userFilter,
|
||||
$this->userDataMapper
|
||||
);
|
||||
} catch (NotFoundException) {
|
||||
throw new BadRequestException(__('User or the old password is not correct'));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
|
||||
final class CountUserService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UserRepository $userRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserFilter $userFilter): int
|
||||
{
|
||||
return $this->userRepository->count($userFilter);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
use PandoraFMS\Modules\Users\Validations\UserValidation;
|
||||
use PandoraFMS\Modules\Shared\Services\Audit;
|
||||
|
||||
final class CreateUserService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Audit $audit,
|
||||
private UserRepository $userRepository,
|
||||
private UserValidation $userValidation
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(User $user): User
|
||||
{
|
||||
$this->userValidation->__invoke($user);
|
||||
|
||||
$user = $this->userRepository->create($user);
|
||||
|
||||
$this->audit->write(
|
||||
'User Management',
|
||||
' Create user #'.$user->getIdUser()
|
||||
);
|
||||
|
||||
// TODO: Campos personalizados.
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Services\Audit;
|
||||
|
||||
final class DeleteUserService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Audit $audit,
|
||||
private UserRepository $userRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(User $user): void
|
||||
{
|
||||
$idUser = $user->getIdUser();
|
||||
|
||||
$this->userRepository->delete($idUser);
|
||||
|
||||
$this->audit->write(
|
||||
'User Management',
|
||||
' Deleted user #'.$idUser
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfileDataMapper;
|
||||
|
||||
final class GetUserService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UserRepository $userRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(string $idUser): User
|
||||
{
|
||||
$userFilter = new UserFilter();
|
||||
|
||||
/*
|
||||
@var User $entityFilter
|
||||
*/
|
||||
$entityFilter = $userFilter->getEntityFilter();
|
||||
$entityFilter->setIdUser($idUser);
|
||||
|
||||
return $this->userRepository->getOne($userFilter);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Users\Entities\UserFilter;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
|
||||
final class ListUserService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UserRepository $userRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserFilter $userFilter): array
|
||||
{
|
||||
return $this->userRepository->list($userFilter);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\Services;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Services\Audit;
|
||||
use PandoraFMS\Modules\Users\Entities\User;
|
||||
use PandoraFMS\Modules\Users\Repositories\UserRepository;
|
||||
use PandoraFMS\Modules\Users\Validations\UserValidation;
|
||||
|
||||
final class UpdateUserService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Audit $audit,
|
||||
private UserRepository $userRepository,
|
||||
private UserValidation $userValidation
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(User $user, User $oldUser): User
|
||||
{
|
||||
$this->userValidation->__invoke($user, $oldUser);
|
||||
|
||||
$user = $this->userRepository->update($user);
|
||||
|
||||
$this->audit->write(
|
||||
'User Management',
|
||||
' Update user #'.$user->getIdUser()
|
||||
);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfile;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Services\CreateUserProfileService;
|
||||
|
||||
final class CreateUserProfileAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private CreateUserProfileService $createUserProfileService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserProfile $userProfile): UserProfile
|
||||
{
|
||||
return $this->createUserProfileService->__invoke($userProfile);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfile;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Services\DeleteUserProfileService;
|
||||
|
||||
final class DeleteUserProfileAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private DeleteUserProfileService $deleteService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserProfile $userProfile): void
|
||||
{
|
||||
$this->deleteService->__invoke($userProfile);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfile;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Services\GetUserProfileService;
|
||||
|
||||
final class GetUserProfileAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private GetUserProfileService $getUserProfileService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(string $idUser, int $idProfile): UserProfile
|
||||
{
|
||||
return $this->getUserProfileService->__invoke($idUser, $idProfile);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Actions;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfileFilter;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Services\CountUserProfileService;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Services\ListUserProfileService;
|
||||
use PandoraFMS\Modules\Shared\Entities\PaginationData;
|
||||
|
||||
final class ListUserProfileAction
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private ListUserProfileService $listUserProfileService,
|
||||
private CountUserProfileService $countUserProfileService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserProfileFilter $userProfileFilter): array
|
||||
{
|
||||
return (new PaginationData(
|
||||
$userProfileFilter->getPage(),
|
||||
$userProfileFilter->getSizePage(),
|
||||
$this->countUserProfileService->__invoke($userProfileFilter),
|
||||
$this->listUserProfileService->__invoke($userProfileFilter)
|
||||
))->toArray();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Actions\CreateUserProfileAction;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfile;
|
||||
use PandoraFMS\Modules\Profiles\Actions\GetProfileAction;
|
||||
use PandoraFMS\Modules\Shared\Controllers\Controller;
|
||||
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
final class CreateUserProfileController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private CreateUserProfileAction $createUserProfileAction,
|
||||
private ValidateAclSystem $acl,
|
||||
private GetUserAction $getUserAction,
|
||||
private GetProfileAction $getProfileAction
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* tags={"Users"},
|
||||
* path="/user/{id}/profile/{idProfile}",
|
||||
* summary="Create user profile",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterProfileId"),
|
||||
* @OA\RequestBody(ref="#/components/requestBodies/requestBodyUserProfile"),
|
||||
* @OA\Response(response=200, ref="#/components/responses/ResponseUserProfile"),
|
||||
* @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
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$user = $this->getUserAction->__invoke($idUser);
|
||||
|
||||
$this->acl->validate(0, 'UM', ' tried to manage user');
|
||||
|
||||
$idProfile = $this->getParam($request, 'idProfile');
|
||||
$profile = $this->getProfileAction->__invoke($idProfile);
|
||||
|
||||
// @var UserProfile $userProfile.
|
||||
$userProfile = $this->fromRequest($request, UserProfile::class);
|
||||
$userProfile->setIdUser($idUser);
|
||||
$userProfile->setIdProfile($idProfile);
|
||||
|
||||
$result = $this->createUserProfileAction->__invoke($userProfile);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Profiles\Actions\GetProfileAction;
|
||||
use PandoraFMS\Modules\Shared\Controllers\Controller;
|
||||
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Actions\DeleteUserProfileAction;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Actions\GetUserProfileAction;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
final class DeleteUserProfileController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private DeleteUserProfileAction $deleteUserProfileAction,
|
||||
private ValidateAclSystem $acl,
|
||||
private GetUserAction $getUserAction,
|
||||
private GetProfileAction $getProfileAction,
|
||||
private GetUserProfileAction $getUserProfileAction
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Delete(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* tags={"Users"},
|
||||
* path="/user/{id}/profile/{idProfile}",
|
||||
* summary="Deletes user profile.",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterProfileId"),
|
||||
* @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
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$user = $this->getUserAction->__invoke($idUser);
|
||||
|
||||
$idProfile = $this->getParam($request, 'idProfile');
|
||||
$profile = $this->getProfileAction->__invoke($idProfile);
|
||||
|
||||
$userProfile = $this->getUserProfileAction->__invoke($idUser, $idProfile);
|
||||
$result = $this->deleteUserProfileAction->__invoke($userProfile);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Profiles\Actions\GetProfileAction;
|
||||
use PandoraFMS\Modules\Shared\Controllers\Controller;
|
||||
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Actions\GetUserProfileAction;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
final class GetUserProfileController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private GetUserProfileAction $getUserProfileAction,
|
||||
private GetUserAction $getUserAction,
|
||||
private GetProfileAction $getProfileAction,
|
||||
private ValidateAclSystem $acl
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* path="/user/{id}/profile/{idProfile}",
|
||||
* tags={"Users"},
|
||||
* summary="show data field user profile",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterProfileId"),
|
||||
* @OA\Response(response=200, ref="#/components/responses/ResponseUserProfile"),
|
||||
* @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
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$user = $this->getUserAction->__invoke($idUser);
|
||||
|
||||
$idProfile = $this->getParam($request, 'idProfile');
|
||||
$this->getProfileAction->__invoke($idProfile);
|
||||
|
||||
$result = $this->getUserProfileAction->__invoke($idUser, $idProfile);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Controllers;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Controllers\Controller;
|
||||
use PandoraFMS\Modules\Shared\Services\ValidateAclSystem;
|
||||
use PandoraFMS\Modules\Users\Actions\GetUserAction;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Actions\ListUserProfileAction;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfileFilter;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
final class ListUserProfileController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private ListUserProfileAction $listUserProfileAction,
|
||||
private GetUserAction $getUserAction,
|
||||
private ValidateAclSystem $acl,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* security={{ "bearerAuth": {}}},
|
||||
* tags={"Users"},
|
||||
* path="/user/{id}/profiles",
|
||||
* summary="List user profiles",
|
||||
* @OA\Parameter(ref="#/components/parameters/parameterIdUser"),
|
||||
* @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/requestBodyUserProfile"),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="List data profiles user 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/UserProfile",
|
||||
* description="Array of profiles"
|
||||
* )
|
||||
* ),
|
||||
* ),
|
||||
* )
|
||||
* }
|
||||
* ),
|
||||
* @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
|
||||
{
|
||||
$idUser = $this->getParam($request, 'id');
|
||||
$user = $this->getUserAction->__invoke($idUser);
|
||||
|
||||
// @var UserProfileFilter $userProfileFilter.
|
||||
$userProfileFilter = $this->fromRequest($request, UserProfileFilter::class);
|
||||
$userProfileFilter->getEntityFilter()->setIdUser($idUser);
|
||||
|
||||
$result = $this->listUserProfileAction->__invoke($userProfileFilter);
|
||||
return $this->getResponse($response, $result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Entities;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Entities\Entity;
|
||||
use PandoraFMS\Modules\Shared\Validators\Validator;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="UserProfile",
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="idUserProfile",
|
||||
* type="integer",
|
||||
* nullable=false,
|
||||
* description="Id user profile",
|
||||
* readOnly=true
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="idUser",
|
||||
* type="string",
|
||||
* nullable=false,
|
||||
* readOnly=true,
|
||||
* description="Id User"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="idProfile",
|
||||
* type="integer",
|
||||
* nullable=false,
|
||||
* readOnly=true,
|
||||
* description="Id Profile"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="idGroup",
|
||||
* type="integer",
|
||||
* nullable=false,
|
||||
* description="Id Group"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="assignedBy",
|
||||
* type="string",
|
||||
* nullable=false,
|
||||
* default=null,
|
||||
* readOnly=true,
|
||||
* description="Create user profile by"
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="ResponseUserProfile",
|
||||
* description="User Profile type object",
|
||||
* content={
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="object",
|
||||
* ref="#/components/schemas/UserProfile",
|
||||
* description="User Profile type object"
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* parameter="parameterProfileId",
|
||||
* name="idProfile",
|
||||
* in="path",
|
||||
* description="Profile id",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer",
|
||||
* default=1
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @OA\RequestBody(
|
||||
* request="requestBodyUserProfile",
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(ref="#/components/schemas/UserProfile")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
final class UserProfile extends Entity
|
||||
{
|
||||
|
||||
private ?int $idUserProfile = null;
|
||||
|
||||
private ?string $idUser = null;
|
||||
|
||||
private ?int $idProfile = null;
|
||||
|
||||
private ?int $idGroup = null;
|
||||
|
||||
private ?string $assignedBy = null;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function fieldsReadOnly(): array
|
||||
{
|
||||
return ['idUserProfile' => 1];
|
||||
}
|
||||
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return [
|
||||
'idUserProfile' => $this->getIdUserProfile(),
|
||||
'idUser' => $this->getIdUser(),
|
||||
'idProfile' => $this->getIdProfile(),
|
||||
'idGroup' => $this->getIdGroup(),
|
||||
'assignedBy' => $this->getAssignedBy(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getValidations(): array
|
||||
{
|
||||
return [
|
||||
'idUserProfile' => [
|
||||
Validator::INTEGER,
|
||||
Validator::GREATEREQUALTHAN,
|
||||
],
|
||||
'idUser' => Validator::STRING,
|
||||
'idProfile' => [
|
||||
Validator::INTEGER,
|
||||
Validator::GREATEREQUALTHAN,
|
||||
],
|
||||
'idGroup' => [
|
||||
Validator::INTEGER,
|
||||
Validator::GREATEREQUALTHAN,
|
||||
],
|
||||
'assignedBy' => Validator::STRING,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function validateFields(array $filters): array
|
||||
{
|
||||
return (new Validator())->validate($filters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of idUserProfile.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getIdUserProfile(): ?int
|
||||
{
|
||||
return $this->idUserProfile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of idUserProfile.
|
||||
*
|
||||
* @param integer $idUserProfile
|
||||
*/
|
||||
public function setIdUserProfile(?int $idUserProfile): self
|
||||
{
|
||||
$this->idUserProfile = $idUserProfile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of idUser.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getIdUser(): ?string
|
||||
{
|
||||
return $this->idUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of idUser.
|
||||
*
|
||||
* @param string $idUser
|
||||
*/
|
||||
public function setIdUser(?string $idUser): self
|
||||
{
|
||||
$this->idUser = $idUser;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of idProfile.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getIdProfile(): ?int
|
||||
{
|
||||
return $this->idProfile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of idProfile.
|
||||
*
|
||||
* @param integer $idProfile
|
||||
*/
|
||||
public function setIdProfile(?int $idProfile): self
|
||||
{
|
||||
$this->idProfile = $idProfile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of idGroup.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getIdGroup(): ?int
|
||||
{
|
||||
return $this->idGroup;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of idGroup.
|
||||
*
|
||||
* @param integer $idGroup
|
||||
*/
|
||||
public function setIdGroup(?int $idGroup): self
|
||||
{
|
||||
$this->idGroup = $idGroup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of assignedBy.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getAssignedBy(): ?string
|
||||
{
|
||||
return $this->assignedBy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of assignedBy.
|
||||
*
|
||||
* @param string $assignedBy
|
||||
*/
|
||||
public function setAssignedBy(?string $assignedBy): self
|
||||
{
|
||||
$this->assignedBy = $assignedBy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\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 UserProfileDataMapper extends DataMapperAbstract
|
||||
{
|
||||
public const TABLE_NAME = 'tusuario_perfil';
|
||||
public const ID_USER_PROFILE = 'id_up';
|
||||
public const ID_USER = 'id_usuario';
|
||||
public const ID_PROFILE = 'id_perfil';
|
||||
public const ID_GROUP = 'id_grupo';
|
||||
public const ASSIGNED_BY = 'assigned_by';
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Repository $repository,
|
||||
private Builder $builder,
|
||||
) {
|
||||
parent::__construct(
|
||||
self::TABLE_NAME,
|
||||
self::ID_USER_PROFILE,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return UserProfile::class;
|
||||
}
|
||||
|
||||
|
||||
public function fromDatabase(array $data): UserProfile
|
||||
{
|
||||
return $this->builder->build(
|
||||
new UserProfile(),
|
||||
[
|
||||
'idUserProfile' => $data[self::ID_USER_PROFILE],
|
||||
'idUser' => $data[self::ID_USER],
|
||||
'idProfile' => $data[self::ID_PROFILE],
|
||||
'idGroup' => $data[self::ID_GROUP],
|
||||
'assignedBy' => $data[self::ASSIGNED_BY],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function toDatabase(MappeableInterface $data): array
|
||||
{
|
||||
/*
|
||||
@var UserProfile $data
|
||||
*/
|
||||
return [
|
||||
self::ID_USER_PROFILE => $data->getIdUserProfile(),
|
||||
self::ID_USER => $data->getIdUser(),
|
||||
self::ID_PROFILE => $data->getIdProfile(),
|
||||
self::ID_GROUP => $data->getIdGroup(),
|
||||
self::ASSIGNED_BY => $data->getAssignedBy(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Entities;
|
||||
|
||||
use PandoraFMS\Modules\Shared\Core\FilterAbstract;
|
||||
use PandoraFMS\Modules\Shared\Validators\Validator;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="UserProfileFilter",
|
||||
* type="object",
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/UserProfile"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="idUserProfile",
|
||||
* default=null,
|
||||
* readOnly=false
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @OA\RequestBody(
|
||||
* request="requestBodyUserProfileFilter",
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(ref="#/components/schemas/UserProfileFilter")
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
final class UserProfileFilter extends FilterAbstract
|
||||
{
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setDefaultFieldOrder(UserProfileDataMapper::ID_USER_PROFILE);
|
||||
$this->setDefaultDirectionOrder($this::ASC);
|
||||
$this->setEntityFilter(new UserProfile());
|
||||
}
|
||||
|
||||
|
||||
public function fieldsTranslate(): array
|
||||
{
|
||||
return [
|
||||
'idUserProfile' => UserProfileDataMapper::ID_USER_PROFILE,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function fieldsReadOnly(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function getValidations(): array
|
||||
{
|
||||
$validations = [];
|
||||
if ($this->getEntityFilter() !== null) {
|
||||
$validations = $this->getEntityFilter()->getValidations();
|
||||
}
|
||||
|
||||
return $validations;
|
||||
}
|
||||
|
||||
|
||||
public function validateFields(array $filters): array
|
||||
{
|
||||
return (new Validator())->validate($filters);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Repositories;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfile;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfileDataMapper;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfileFilter;
|
||||
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
|
||||
use PandoraFMS\Modules\Shared\Repositories\Repository;
|
||||
|
||||
class UserProfileRepository
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private Repository $repository,
|
||||
private UserProfileDataMapper $userProfileDataMapper
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return UserProfile[],
|
||||
*/
|
||||
public function list(UserProfileFilter $userProfileFilter): array
|
||||
{
|
||||
return $this->repository->__list(
|
||||
$userProfileFilter,
|
||||
$this->userProfileDataMapper
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function count(UserProfileFilter $userProfileFilter): int
|
||||
{
|
||||
return $this->repository->__count(
|
||||
$userProfileFilter,
|
||||
$this->userProfileDataMapper
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getOne(UserProfileFilter $userProfileFilter): UserProfile
|
||||
{
|
||||
return $this->repository->__getOne(
|
||||
$userProfileFilter,
|
||||
$this->userProfileDataMapper
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function create(UserProfile $userProfile): UserProfile
|
||||
{
|
||||
try {
|
||||
$id = $this->repository->__create($userProfile, $this->userProfileDataMapper);
|
||||
return $userProfile->setIdUserProfile($id);
|
||||
} catch (\Throwable $th) {
|
||||
throw new BadRequestException(__('User profile already exists in the bbdd:'.$th->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function update(UserProfile $userProfile): UserProfile
|
||||
{
|
||||
return $this->repository->__update(
|
||||
$userProfile,
|
||||
$this->userProfileDataMapper,
|
||||
$userProfile->getIdUserProfile()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function delete(int $id, ?string $key=null): void
|
||||
{
|
||||
$this->repository->__delete($id, $this->userProfileDataMapper, $key);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace PandoraFMS\Modules\Users\UserProfiles\Services;
|
||||
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Entities\UserProfileFilter;
|
||||
use PandoraFMS\Modules\Users\UserProfiles\Repositories\UserProfileRepository;
|
||||
|
||||
final class CountUserProfileService
|
||||
{
|
||||
|
||||
|
||||
public function __construct(
|
||||
private UserProfileRepository $userProfileRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UserProfileFilter $userProfileFilter): int
|
||||
{
|
||||
return $this->userProfileRepository->count($userProfileFilter);
|
||||
}
|
||||
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user