Cli user
This commit is contained in:
10
app/resources/routes/96_admin.php
Normal file
10
app/resources/routes/96_admin.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
$app->group('/admin', function($app) {
|
||||||
|
$files = new FilesystemIterator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'admin']));
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file->isDir()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
include_once $file->getRealPath();
|
||||||
|
}
|
||||||
|
});
|
6
app/resources/routes/admin/users.php
Normal file
6
app/resources/routes/admin/users.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
use Incoviba\Controller\Admin\Users;
|
||||||
|
|
||||||
|
$app->group('/users', function($app) {
|
||||||
|
$app->get('[/]', Users::class);
|
||||||
|
});
|
13
app/resources/routes/api/admin.php
Normal file
13
app/resources/routes/api/admin.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
$app->group('/admin', function($app) {
|
||||||
|
$folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'admin']);
|
||||||
|
if (file_exists($folder)) {
|
||||||
|
$files = new FilesystemIterator($folder);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file->isDir()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
include_once $file->getRealPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
6
app/resources/routes/api/admin/users.php
Normal file
6
app/resources/routes/api/admin/users.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
use Incoviba\Controller\API\Admin\Users;
|
||||||
|
|
||||||
|
$app->group('/users', function($app) {
|
||||||
|
$app->post('/add[/]', Users::class . ':add');
|
||||||
|
});
|
4
app/resources/routes/api/login.php
Normal file
4
app/resources/routes/api/login.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
use Incoviba\Controller\API\Login;
|
||||||
|
|
||||||
|
$app->post('/login[/]', Login::class);
|
@ -4,6 +4,10 @@ use Incoviba\Controller\API\Money;
|
|||||||
$app->group('/money', function($app) {
|
$app->group('/money', function($app) {
|
||||||
$app->post('/ipc[/]', [Money::class, 'ipc']);
|
$app->post('/ipc[/]', [Money::class, 'ipc']);
|
||||||
$app->post('/uf[/]', [Money::class, 'uf']);
|
$app->post('/uf[/]', [Money::class, 'uf']);
|
||||||
|
$app->group('/ufs', function($app) {
|
||||||
|
$app->post('[/]', [Money::class, 'updateUfs']);
|
||||||
|
$app->get('[/]', [Money::class, 'ufs']);
|
||||||
|
});
|
||||||
$app->post('/many[/]', [Money::class, 'getMany']);
|
$app->post('/many[/]', [Money::class, 'getMany']);
|
||||||
$app->post('[/]', [Money::class, 'get']);
|
$app->post('[/]', [Money::class, 'get']);
|
||||||
});
|
});
|
||||||
|
100
app/resources/views/admin/users.blade.php
Normal file
100
app/resources/views/admin/users.blade.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
@extends('layout.base')
|
||||||
|
|
||||||
|
@section('page_content')
|
||||||
|
<div class="ui container">
|
||||||
|
<h2 class="ui header">Usuarios</h2>
|
||||||
|
<table class="ui table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nombre</th>
|
||||||
|
<th class="right aligned">
|
||||||
|
<button class="ui mini green icon button" id="create-user-button">
|
||||||
|
<i class="plus icon"></i>
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($users as $user)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $user->name }}</td>
|
||||||
|
<td class="right aligned">
|
||||||
|
<button class="ui mini blue icon button">
|
||||||
|
<i class="edit icon"></i>
|
||||||
|
</button>
|
||||||
|
<button class="ui mini red icon button">
|
||||||
|
<i class="trash icon"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="ui modal" id="create-user-modal">
|
||||||
|
<i class="close icon"></i>
|
||||||
|
<div class="header">
|
||||||
|
Crear usuario
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<form class="ui form">
|
||||||
|
<div class="field">
|
||||||
|
<label>Nombre</label>
|
||||||
|
<input type="text" name="name" placeholder="Nombre">
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Correo</label>
|
||||||
|
<input type="email" name="email" placeholder="Correo">
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Contraseña</label>
|
||||||
|
<input type="password" name="password" placeholder="Contraseña">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<div class="ui black deny button">
|
||||||
|
Cancelar
|
||||||
|
</div>
|
||||||
|
<div class="ui positive right labeled icon button">
|
||||||
|
Crear
|
||||||
|
<i class="checkmark icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@include('layout.body.scripts.cryptojs')
|
||||||
|
|
||||||
|
@push('page_scripts')
|
||||||
|
<script>
|
||||||
|
function encryptPassword(password) {
|
||||||
|
const passphrase = Math.floor(Math.random() * Date.now()).toString()
|
||||||
|
const encrypted = CryptoJS.AES.encrypt(password, passphrase)
|
||||||
|
return [passphrase, encrypted.toString()].join('')
|
||||||
|
}
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#create-user-modal').modal({
|
||||||
|
onApprove: function() {
|
||||||
|
const url = '{{$urls->api}}/admin/users/add'
|
||||||
|
const method = 'post'
|
||||||
|
const body = new FormData(document.querySelector('#create-user-modal form'))
|
||||||
|
body.set('password', encryptPassword(body.get('password')))
|
||||||
|
fetchAPI(url, {method, body}).then(response => {
|
||||||
|
if (!response) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.json().then(result => {
|
||||||
|
if (result.success) {
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$('#create-user-button').on('click', function () {
|
||||||
|
$('#create-user-modal').modal('show')
|
||||||
|
})
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
@ -15,6 +15,7 @@ return [
|
|||||||
return new Incoviba\Middleware\API(
|
return new Incoviba\Middleware\API(
|
||||||
$container->get(Psr\Http\Message\ResponseFactoryInterface::class),
|
$container->get(Psr\Http\Message\ResponseFactoryInterface::class),
|
||||||
$container->get(Incoviba\Service\Login::class),
|
$container->get(Incoviba\Service\Login::class),
|
||||||
|
$container->get(Psr\Log\LoggerInterface::class),
|
||||||
$container->get('API_KEY')
|
$container->get('API_KEY')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ return [
|
|||||||
Incoviba\Service\Login::class => function(ContainerInterface $container) {
|
Incoviba\Service\Login::class => function(ContainerInterface $container) {
|
||||||
return new Incoviba\Service\Login(
|
return new Incoviba\Service\Login(
|
||||||
$container->get(Incoviba\Repository\Login::class),
|
$container->get(Incoviba\Repository\Login::class),
|
||||||
|
$container->get(Incoviba\Repository\User::class),
|
||||||
$container->get('COOKIE_NAME'),
|
$container->get('COOKIE_NAME'),
|
||||||
$container->get('MAX_LOGIN_HOURS'),
|
$container->get('MAX_LOGIN_HOURS'),
|
||||||
$container->has('COOKIE_DOMAIN') ? $container->get('COOKIE_DOMAIN') : '',
|
$container->has('COOKIE_DOMAIN') ? $container->get('COOKIE_DOMAIN') : '',
|
||||||
@ -72,8 +73,8 @@ return [
|
|||||||
)
|
)
|
||||||
->register('xlsx', Incoviba\Service\Informe\Excel::class);
|
->register('xlsx', Incoviba\Service\Informe\Excel::class);
|
||||||
},
|
},
|
||||||
\Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Excel::class => function(ContainerInterface $container) {
|
Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Excel::class => function(ContainerInterface $container) {
|
||||||
return new \Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Excel(
|
return new Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Excel(
|
||||||
$container->get(Psr\Log\LoggerInterface::class),
|
$container->get(Psr\Log\LoggerInterface::class),
|
||||||
$container->get('folders')->get('informes'),
|
$container->get('folders')->get('informes'),
|
||||||
$container->get(Incoviba\Service\UF::class),
|
$container->get(Incoviba\Service\UF::class),
|
||||||
|
30
app/src/Controller/API/Admin/Users.php
Normal file
30
app/src/Controller/API/Admin/Users.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Controller\API\Admin;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
||||||
|
use Incoviba\Controller\API\withJson;
|
||||||
|
use Incoviba\Service;
|
||||||
|
|
||||||
|
class Users
|
||||||
|
{
|
||||||
|
use withJson;
|
||||||
|
|
||||||
|
public function add(ServerRequestInterface $request, ResponseInterface $response, Service\Login $loginService): ResponseInterface
|
||||||
|
{
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
$output = [
|
||||||
|
'input' => array_filter($body, fn($key) => $key !== 'password', ARRAY_FILTER_USE_KEY),
|
||||||
|
'success' => false,
|
||||||
|
'user' => null
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
$user = $loginService->addUser($body);
|
||||||
|
$output['success'] = true;
|
||||||
|
$output['user'] = $user;
|
||||||
|
} catch (EmptyResult) {}
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
}
|
33
app/src/Controller/API/Login.php
Normal file
33
app/src/Controller/API/Login.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Controller\API;
|
||||||
|
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Repository;
|
||||||
|
use Incoviba\Service;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class Login
|
||||||
|
{
|
||||||
|
use withJson;
|
||||||
|
|
||||||
|
public function __invoke(ServerRequestInterface $request, ResponseInterface $response,
|
||||||
|
Repository\User $userRepository,
|
||||||
|
Repository\Login $loginRepository,
|
||||||
|
Service\Login $loginService): ResponseInterface
|
||||||
|
{
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
$output = [
|
||||||
|
'username' => $body['username'],
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
$user = $userRepository->fetchByName($body['username']);
|
||||||
|
if ($user->validate($body['password'])) {
|
||||||
|
$loginService->login($user);
|
||||||
|
$output['token'] = $loginService->getToken();
|
||||||
|
}
|
||||||
|
} catch (EmptyResult) {}
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ use Incoviba\Controller\withRedis;
|
|||||||
use Incoviba\Service;
|
use Incoviba\Service;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
class Money
|
class Money
|
||||||
{
|
{
|
||||||
@ -77,6 +78,31 @@ class Money
|
|||||||
$output['uf'] = $ufService->get($date);
|
$output['uf'] = $ufService->get($date);
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
|
public function ufs(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService): ResponseInterface
|
||||||
|
{
|
||||||
|
$redisKey = 'uf';
|
||||||
|
$output = [
|
||||||
|
'ufs' => []
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
$output['ufs'] = (array) $this->fetchRedis($redisService, $redisKey);
|
||||||
|
} catch (EmptyRedis) {}
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
public function updateUfs(ServerRequestInterface $request, ResponseInterface $response,
|
||||||
|
LoggerInterface $logger,
|
||||||
|
Service\UF $ufService): ResponseInterface
|
||||||
|
{
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
$dates = array_map(function($dateData) {
|
||||||
|
return new DateTimeImmutable($dateData);
|
||||||
|
}, $body['fechas']);
|
||||||
|
$output = [
|
||||||
|
'input' => $body,
|
||||||
|
'ufs' => $ufService->updateMany($dates)
|
||||||
|
];
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
public function ipc(ServerRequestInterface $request, ResponseInterface $response,
|
public function ipc(ServerRequestInterface $request, ResponseInterface $response,
|
||||||
Service\IPC $ipcService): ResponseInterface
|
Service\IPC $ipcService): ResponseInterface
|
||||||
{
|
{
|
||||||
|
21
app/src/Controller/Admin/Users.php
Normal file
21
app/src/Controller/Admin/Users.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Controller\Admin;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Common\Alias\View;
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
||||||
|
use Incoviba\Repository;
|
||||||
|
|
||||||
|
class Users
|
||||||
|
{
|
||||||
|
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view,
|
||||||
|
Repository\User $userRepository): ResponseInterface
|
||||||
|
{
|
||||||
|
$users = [];
|
||||||
|
try {
|
||||||
|
$users = $userRepository->fetchAll('name');
|
||||||
|
} catch (EmptyResult) {}
|
||||||
|
return $view->render($response, 'admin.users', compact('users'));
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,10 @@ use function setcookie;
|
|||||||
|
|
||||||
class Login
|
class Login
|
||||||
{
|
{
|
||||||
public function __construct(protected Repository\Login $repository, protected string $cookie_name, protected int $max_login_time, protected string $domain = '', protected string $path = '', protected string $cookie_separator = ':')
|
public function __construct(protected Repository\Login $repository, protected Repository\User $userRepository,
|
||||||
|
protected string $cookie_name,
|
||||||
|
protected int $max_login_time, protected string $domain = '',
|
||||||
|
protected string $path = '', protected string $cookie_separator = ':')
|
||||||
{
|
{
|
||||||
$this->loadCookie();
|
$this->loadCookie();
|
||||||
}
|
}
|
||||||
@ -23,19 +26,18 @@ class Login
|
|||||||
protected string $selector = '';
|
protected string $selector = '';
|
||||||
protected string $token = '';
|
protected string $token = '';
|
||||||
|
|
||||||
public function isIn(): bool
|
public function isIn(?string $selector = null, ?string $sentToken = null): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$login = $this->repository->fetchActiveBySelector($this->selector);
|
$login = $this->repository->fetchActiveBySelector($selector ?? $this->selector);
|
||||||
if (!$this->validToken($login)) {
|
if (!$this->validToken($login, $sentToken)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$now = new DateTimeImmutable();
|
$now = new DateTimeImmutable();
|
||||||
if ($login->dateTime->add(new DateInterval("PT{$this->max_login_time}H")) > $now) {
|
if ($login->dateTime->add(new DateInterval("PT{$this->max_login_time}H")) > $now) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (PDOException|EmptyResult) {
|
} catch (PDOException|EmptyResult) {}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public function getUser(): Model\User
|
public function getUser(): Model\User
|
||||||
@ -54,6 +56,23 @@ class Login
|
|||||||
{
|
{
|
||||||
return $this->cookie_separator;
|
return $this->cookie_separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addUser(array $data): Model\User
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->userRepository->fetchByName($data['name']);
|
||||||
|
} catch (EmptyResult) {
|
||||||
|
list($passphrase, $encrypted) = $this->splitPassword($data['password']);
|
||||||
|
$password = $this->cryptoJs_aes_decrypt($encrypted, $passphrase);
|
||||||
|
$password = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
$user = $this->userRepository->create([
|
||||||
|
'name' => $data['name'],
|
||||||
|
'password' => $password,
|
||||||
|
'enabled' => $data['enabled'] ?? 1
|
||||||
|
]);
|
||||||
|
return $this->userRepository->save($user);
|
||||||
|
}
|
||||||
|
}
|
||||||
public function validateUser(Model\User $user, string $encryptedPassword): bool
|
public function validateUser(Model\User $user, string $encryptedPassword): bool
|
||||||
{
|
{
|
||||||
list($passphrase, $encrypted) = $this->splitPassword($encryptedPassword);
|
list($passphrase, $encrypted) = $this->splitPassword($encryptedPassword);
|
||||||
@ -106,6 +125,10 @@ class Login
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public function parseToken(Model\Login $login): string
|
||||||
|
{
|
||||||
|
return implode($this->cookie_separator, [$login->selector, $login->token]);
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadCookie(): void
|
protected function loadCookie(): void
|
||||||
{
|
{
|
||||||
@ -145,8 +168,11 @@ class Login
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function validToken(Model\Login $login): bool
|
protected function validToken(Model\Login $login, ?string $sentToken = null): bool
|
||||||
{
|
{
|
||||||
|
if ($sentToken !== null) {
|
||||||
|
return password_verify($sentToken, $login->token);
|
||||||
|
}
|
||||||
return password_verify($this->token, $login->token);
|
return password_verify($this->token, $login->token);
|
||||||
}
|
}
|
||||||
protected function generateToken(Model\Login $login): array
|
protected function generateToken(Model\Login $login): array
|
||||||
|
@ -4,12 +4,14 @@ namespace Incoviba\Service;
|
|||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
class UF
|
class UF
|
||||||
{
|
{
|
||||||
protected string $redisKey = 'uf';
|
protected string $redisKey = 'uf';
|
||||||
|
|
||||||
public function __construct(protected Redis $redisService, protected Money $moneyService) {}
|
public function __construct(protected Redis $redisService, protected Money $moneyService,
|
||||||
|
protected LoggerInterface $logger) {}
|
||||||
|
|
||||||
public function get(?DateTimeInterface $date = null): float
|
public function get(?DateTimeInterface $date = null): float
|
||||||
{
|
{
|
||||||
@ -25,12 +27,36 @@ class UF
|
|||||||
$uf = $ufs[$date->format('Y-m-d')];
|
$uf = $ufs[$date->format('Y-m-d')];
|
||||||
} catch (EmptyRedis) {
|
} catch (EmptyRedis) {
|
||||||
$uf = $this->moneyService->getUF($date);
|
$uf = $this->moneyService->getUF($date);
|
||||||
|
if ($uf === 0.0) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
$ufs[$date->format('Y-m-d')] = $uf;
|
$ufs[$date->format('Y-m-d')] = $uf;
|
||||||
ksort($ufs);
|
ksort($ufs);
|
||||||
$this->redisService->set($this->redisKey, json_encode($ufs), 60 * 60 * 24 * 30);
|
$this->redisService->set($this->redisKey, json_encode($ufs), 60 * 60 * 24 * 30);
|
||||||
}
|
}
|
||||||
return $uf;
|
return $uf;
|
||||||
}
|
}
|
||||||
|
public function updateMany(array $dates): array
|
||||||
|
{
|
||||||
|
$ufs = [];
|
||||||
|
try {
|
||||||
|
$ufs = json_decode($this->redisService->get($this->redisKey), JSON_OBJECT_AS_ARRAY);
|
||||||
|
} catch (EmptyRedis) {}
|
||||||
|
$updated = [];
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
if (!isset($ufs[$date->format('Y-m-d')]) or $ufs[$date->format('Y-m-d')] === 0) {
|
||||||
|
$uf = $this->moneyService->getUF($date);
|
||||||
|
if ($uf === 0.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$updated[$date->format('Y-m-d')] = $uf;
|
||||||
|
$ufs[$date->format('Y-m-d')] = $this->moneyService->getUF($date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksort($ufs);
|
||||||
|
$this->redisService->set($this->redisKey, json_encode($ufs), 60 * 60 * 24 * 30);
|
||||||
|
return $updated;
|
||||||
|
}
|
||||||
public function transform(DateTimeInterface $date, float $input, string $from = 'uf'): float
|
public function transform(DateTimeInterface $date, float $input, string $from = 'uf'): float
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Incoviba\Common\Alias;
|
namespace Incoviba\Common\Alias;
|
||||||
|
|
||||||
|
use Incoviba\Common\Implement\Message;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Symfony\Component\Console\Application as Base;
|
use Symfony\Component\Console;
|
||||||
|
use Incoviba\Common\Concept;
|
||||||
|
|
||||||
class Application extends Base
|
class Application extends Console\Application
|
||||||
{
|
{
|
||||||
public function __construct(protected ContainerInterface $container, string $name = 'UNKNOWN', string $version = 'UNKNOWN')
|
public function __construct(protected ContainerInterface $container, string $name = 'UNKNOWN', string $version = 'UNKNOWN')
|
||||||
{
|
{
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
"name": "incoviba/cli",
|
"name": "incoviba/cli",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
"symfony/console": "^6.3",
|
|
||||||
"php-di/php-di": "^7.0",
|
|
||||||
"guzzlehttp/guzzle": "^7.8",
|
"guzzlehttp/guzzle": "^7.8",
|
||||||
"monolog/monolog": "^3.5"
|
"monolog/monolog": "^3.5",
|
||||||
|
"php-di/php-di": "^7.0",
|
||||||
|
"symfony/console": "^6.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^10.4",
|
"phpunit/phpunit": "^10.4",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
$app->add($app->getContainer()->get(Incoviba\Command\Money\UF::class));
|
$app->add($app->getContainer()->get(Incoviba\Command\Money\UF::class));
|
||||||
$app->add($app->getContainer()->get(Incoviba\Command\Money\IPC::class));
|
$app->add($app->getContainer()->get(Incoviba\Command\Money\IPC::class));
|
||||||
|
$app->add($app->getContainer()->get(Incoviba\Command\Money\UF\Update::class));
|
||||||
|
@ -10,6 +10,10 @@ return [
|
|||||||
$arr['resources'],
|
$arr['resources'],
|
||||||
'commands'
|
'commands'
|
||||||
]);
|
]);
|
||||||
|
$arr['cache'] = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
$arr['base'],
|
||||||
|
'cache'
|
||||||
|
]);
|
||||||
return (object) $arr;
|
return (object) $arr;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Psr\Http\Client\ClientInterface::class => function(ContainerInterface $container) {
|
Incoviba\Service\Login::class => function(ContainerInterface $container) {
|
||||||
return new GuzzleHttp\Client([
|
$client = new GuzzleHttp\Client([
|
||||||
'base_uri' => $container->get('API_URL'),
|
'base_uri' => $container->get('API_URL'),
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'Authorization' => [
|
'Authorization' => [
|
||||||
@ -11,5 +11,23 @@ return [
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
return new Incoviba\Service\Login(
|
||||||
|
$client,
|
||||||
|
$container->get(Psr\Log\LoggerInterface::class),
|
||||||
|
implode(DIRECTORY_SEPARATOR, [$container->get('folders')->cache, 'token']),
|
||||||
|
$container->get('API_USERNAME'),
|
||||||
|
$container->get('API_PASSWORD')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Psr\Http\Client\ClientInterface::class => function(ContainerInterface $container) {
|
||||||
|
$login = $container->get(Incoviba\Service\Login::class);
|
||||||
|
return new GuzzleHttp\Client([
|
||||||
|
'base_uri' => $container->get('API_URL'),
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => [
|
||||||
|
"Bearer {$login->getKey($container->get('API_KEY'))}"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -15,6 +15,7 @@ class Full extends Command
|
|||||||
'comunas',
|
'comunas',
|
||||||
'money:ipc',
|
'money:ipc',
|
||||||
'money:uf',
|
'money:uf',
|
||||||
|
'money:uf:update',
|
||||||
'proyectos:activos',
|
'proyectos:activos',
|
||||||
'ventas:cierres:vigentes',
|
'ventas:cierres:vigentes',
|
||||||
'ventas:cuotas:hoy',
|
'ventas:cuotas:hoy',
|
||||||
|
47
cli/src/Command/Money/UF/Update.php
Normal file
47
cli/src/Command/Money/UF/Update.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Command\Money\UF;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use Symfony\Component\Console;
|
||||||
|
use Incoviba\Common\Alias\Command;
|
||||||
|
|
||||||
|
#[Console\Attribute\AsCommand(
|
||||||
|
name: 'money:uf:update'
|
||||||
|
)]
|
||||||
|
class Update extends Command
|
||||||
|
{
|
||||||
|
public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
|
||||||
|
{
|
||||||
|
$this->logger->debug("Running {$this->getName()}");
|
||||||
|
$url = '/api/money/ufs';
|
||||||
|
$response = $this->client->get($url);
|
||||||
|
$output->writeln("GET {$url}");
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$this->logger->error("Error: [{$response->getStatusCode()}] {$response->getReasonPhrase()}");
|
||||||
|
return Console\Command\Command::FAILURE;
|
||||||
|
}
|
||||||
|
$data = json_decode($response->getBody()->getContents(), JSON_OBJECT_AS_ARRAY)['ufs'];
|
||||||
|
$zeros = [];
|
||||||
|
foreach ($data as $date => $value) {
|
||||||
|
if ($value === 0) {
|
||||||
|
$zeros[] = $date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($zeros) > 0) {
|
||||||
|
$output->writeln('Updating ' . count($zeros) . ' UFs');
|
||||||
|
$uri = '/api/money/ufs';
|
||||||
|
$response = $this->client->post($uri, [
|
||||||
|
'body' => http_build_query(['fechas' => $zeros]),
|
||||||
|
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded']
|
||||||
|
]);
|
||||||
|
$output->writeln("POST {$uri}");
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$this->logger->error("Error: [{$response->getStatusCode()}] {$response->getReasonPhrase()}");
|
||||||
|
return Console\Command\Command::FAILURE;
|
||||||
|
}
|
||||||
|
$body = json_decode($response->getBody()->getContents(), JSON_OBJECT_AS_ARRAY);
|
||||||
|
$output->writeln('Updated ' . count($body['ufs']) . ' UFs');
|
||||||
|
}
|
||||||
|
return Console\Command\Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
59
cli/src/Service/Login.php
Normal file
59
cli/src/Service/Login.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Service;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Psr\Http\Client\ClientExceptionInterface;
|
||||||
|
use Psr\Http\Client\ClientInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class Login
|
||||||
|
{
|
||||||
|
public function __construct(protected ClientInterface $client, protected LoggerInterface $logger,
|
||||||
|
protected string $tokenFilename,
|
||||||
|
protected string $username, protected string $password) {}
|
||||||
|
|
||||||
|
public function login(): string
|
||||||
|
{
|
||||||
|
$url = '/api/login';
|
||||||
|
try {
|
||||||
|
$response = $this->client->request('POST', $url, [
|
||||||
|
'body' => http_build_query([
|
||||||
|
'username' => $this->username,
|
||||||
|
'password' => $this->password
|
||||||
|
]),
|
||||||
|
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded']
|
||||||
|
]);
|
||||||
|
} catch (ClientExceptionInterface $exception) {
|
||||||
|
$this->logger->error($exception);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
$body = $response->getBody()->getContents();
|
||||||
|
$data = json_decode($body, true);
|
||||||
|
if (!key_exists('token', $data)) {
|
||||||
|
$this->logger->error('Token not found');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
file_put_contents($this->tokenFilename, $data['token']);
|
||||||
|
return $data['token'];
|
||||||
|
}
|
||||||
|
public function retrieveToken(): string
|
||||||
|
{
|
||||||
|
if (!file_exists($this->tokenFilename)) {
|
||||||
|
throw new Exception('Token file not found');
|
||||||
|
}
|
||||||
|
return file_get_contents($this->tokenFilename);
|
||||||
|
}
|
||||||
|
public function getKey(string $apiKey, string $separator = 'g'): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$token = $this->retrieveToken();
|
||||||
|
} catch (Exception) {
|
||||||
|
$token = $this->login();
|
||||||
|
}
|
||||||
|
return implode('', [md5($apiKey), $separator, $token]);
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- redisinsight:/data
|
- redisinsight:/data
|
||||||
ports:
|
ports:
|
||||||
- "5540:5540"
|
- "${INSIGHT_PORT:-5540}:5540"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
redisinsight: {}
|
redisinsight: {}
|
||||||
|
Reference in New Issue
Block a user