diff --git a/bootstrap/app.php b/bootstrap/app.php index eabb339..4a84fe0 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -8,8 +8,8 @@ $container_builder = new DI\ContainerBuilder(); $folders = [ 'common' ]; -if (isset($_ENV)) { - $folders []= $_ENV; +if (isset($__environment)) { + $folders []= $__environment; } $file = 'config.php'; @@ -42,4 +42,7 @@ foreach ($folders as $folder) { } } +$dotenv = Dotenv\Dotenv::createImmutable($container->get('folders.base')); +$dotenv->load(); + include_once implode(DIRECTORY_SEPARATOR, [$app->getContainer()->get('folders.routes'), 'router.php']); diff --git a/bootstrap/web.php b/bootstrap/web.php index b028c05..23ed00d 100644 --- a/bootstrap/web.php +++ b/bootstrap/web.php @@ -1,3 +1,3 @@ 'https://img.freepik.com/free-icon/santiago-metro-logo_318-66588.jpg?size=338&ext=jpg', - 'urls.notaria.turno' => 'http://www.notariasdeturno.cl', + 'urls.notaria.turno' => 'https://www.notariosyconservadores.cl/notarias-de-turno/', 'urls.fojas' => 'http://fojas.cl/?motv=vista_descarga_web&cons_sel=not_patricrabybenavent', 'urls.atencion' => 'https://zeroq.cl/#/local/notaria-patricio-raby/48', 'urls.atencion.logo' => 'https://zeroq.cl/img/logo-small.png', 'urls.map' => 'https://maps.google.com/maps?hl=es&q=Notaria%20Patricio%20Raby+(Notaria%20Patricio%20Raby)&ie=UTF8&z=16&iwloc=B&output=embed', 'urls.map2' => 'https://www.google.com/maps/embed/v1/place?q=notaria+patricio+raby&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8', + 'urls.direccion' => 'https://goo.gl/maps/xcxs1SQ9BPAbUDi69', 'styles' => [ 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.4/semantic.min.css', DI\string(implode('/', ['{urls.styles}', 'iconmoon.css'])), @@ -85,5 +86,13 @@ return [ 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.4/semantic.min.js', 'https://friconix.com/cdn/friconix.js' - ] + ], + 'app.cookie.name' => 'login', + 'app.cookie.time' => 20 * 60 * 60, // 20 min + 'files.login' => 'login.yml', + 'urls.login' => DI\string(implode('/', [ + '{urls.base}', + 'admin', + 'login' + ])) ]; diff --git a/bootstrap/web/middleware.php b/bootstrap/web/middleware.php index aab4835..637b9fa 100644 --- a/bootstrap/web/middleware.php +++ b/bootstrap/web/middleware.php @@ -1,11 +1,2 @@ add(new ProVM\NotariaRaby\Common\Middleware\Blade($app->getContainer())); -$app->add(new Tuupola\Middleware\HttpBasicAuthentication([ - 'path' => $app->getContainer()->get('urls.base') . '/admin', - 'ignore' => [ - '/admin/login' - ], - 'users' => [ - 'admin' => 'admin' - ] -])); diff --git a/bootstrap/web/setup.php b/bootstrap/web/setup.php index b872d8f..ea9f2fd 100644 --- a/bootstrap/web/setup.php +++ b/bootstrap/web/setup.php @@ -24,7 +24,8 @@ return [ 'url' => $container->get('urls.atencion'), 'logo' => $container->get('urls.atencion.logo') ], - 'uploads' => $container->get('urls.uploads') + 'uploads' => $container->get('urls.uploads'), + 'direccion' => $container->get('urls.direccion') ], 'horario' => $horario, 'styles' => $container->get('styles'), @@ -38,6 +39,22 @@ return [ $manager->addFolder('data', $c->get('folders.data')); return $manager; }, + ProVM\NotariaRaby\Common\Service\Login::class => function(Container $c) { + return new ProVM\NotariaRaby\Common\Service\Login( + $c->get('app.cookie.name'), + $c->get('app.cookie.time'), + getenv('ADMIN_PASSWORD'), + $c->get('files.login'), + $c->get(ProVM\Common\Service\Filemanager::class) + ); + }, + ProVM\NotariaRaby\Common\Middleware\Auth::class => function(Container $c) { + return new ProVM\NotariaRaby\Common\Middleware\Auth( + ['admin'], + $c->get('urls.login'), + $c->get(ProVM\NotariaRaby\Common\Service\Login::class) + ); + }, Nette\Mail\SendmailMailer::class => DI\create(), Nette\Mail\SmtpMailer::class => function(Container $c) { return new Nette\Mail\SmtpMailer($c->get('email')); diff --git a/common/Controller/Web/Admin/Clave.php b/common/Controller/Web/Admin/Clave.php new file mode 100644 index 0000000..8abff9a --- /dev/null +++ b/common/Controller/Web/Admin/Clave.php @@ -0,0 +1,44 @@ +render($response, 'admin.clave'); + } + public function do_edit(Request $request, Response $response, Container $container, Filemanager $filemanager, Login $service): Response { + $filename = implode(DIRECTORY_SEPARATOR, [ + dirname(__DIR__, 4), + '.env' + ]); + $vars = []; + if (file_exists($filename)) { + $vars = explode(PHP_EOL, trim(file_get_contents($filename))); + } + $i = 0; + foreach ($vars as $i => $var) { + if (strpos($var, 'ADMIN_PASSWORD=') !== false) { + break; + } + } + $post = $request->getParsedBody(); + $enc = password_hash($post['clave'], \PASSWORD_DEFAULT); + $vars[$i] = implode('=', [ + 'ADMIN_PASSWORD', + '"' . $enc . '"' + ]); + file_put_contents($filename, implode(PHP_EOL, $vars)); + return $response + ->withHeader('Location', implode('/', [ + $container->get('urls.base'), + 'admin' + ])) + ->withStatus(301); + } +} diff --git a/common/Controller/Web/Admin/Login.php b/common/Controller/Web/Admin/Login.php index 2f7217a..62c0d4c 100644 --- a/common/Controller/Web/Admin/Login.php +++ b/common/Controller/Web/Admin/Login.php @@ -1,12 +1,23 @@ render($response, 'admin.login'); } + public function do_login(Request $request, Response $response, Service $login, Container $container): Response { + $login->login($request); + return $response + ->withHeader('Location', implode('/', [ + $container->get('urls.base'), + 'admin' + ])) + ->withStatus(301); + } } diff --git a/common/Controller/Web/Home.php b/common/Controller/Web/Home.php index 6a07023..fabba41 100644 --- a/common/Controller/Web/Home.php +++ b/common/Controller/Web/Home.php @@ -12,7 +12,7 @@ class Home { public function __invoke(Request $request, Response $response, View $view, Filemanager $manager, Container $container): Response { $banner = (object) [ 'titulo' => "5° NOTARÍA DE SANTIAGO", - 'contenido' => "Gertrudis Echenique 30, of. 32, El Golf\n Metro Alcantara" + 'contenido' => 'Gertrudis Echenique 30, of. 32, El Golf' . "\n" . ' Metro Alcantara' ]; $links = $manager->folder('data')->load('documentos.yml'); diff --git a/common/Middleware/Auth.php b/common/Middleware/Auth.php new file mode 100644 index 0000000..d7ee2cf --- /dev/null +++ b/common/Middleware/Auth.php @@ -0,0 +1,28 @@ +users = $users; + $this->login_url = $login_url; + $this->login = $service; + } + public function __invoke(Request $request, Handler $handler): Response { + $response = $handler->handle($request); + + $is_logged_in = $this->login->checkAuth($request); + if (!$is_logged_in and $request->getRequestTarget() != $this->login_url) { + return $response + ->withHeader('Location', $this->login_url) + ->withStatus(301); + } + return $response; + } +} diff --git a/common/Service/Login.php b/common/Service/Login.php new file mode 100644 index 0000000..27ac031 --- /dev/null +++ b/common/Service/Login.php @@ -0,0 +1,110 @@ +cookie_name = $cookie_name; + $this->time_limit = $time_limit; + $this->password = $encrypted_password; + $this->filename = $login_file; + $this->manager = $filemanager; + } + + protected $selector; + protected $token; + public function loadCookie() { + if (isset($_COOKIE[$this->cookie_name])) { + list($s, $t) = \explode(':', $_COOKIE[$this->cookie_name]); + $this->selector = $s; + $this->token = $t; + } + } + public function saveCookie() { + $now = Carbon::now(); + $exp = $now->addSeconds($this->time_limit); + \setcookie($this->cookie_name, implode(':', [$this->selector, $this->token]), $exp->timestamp, '/'); + } + public function removeCookie() { + \setcookie($this->cookie_name, '', Carbon::now()->timestamp, '/'); + } + protected function generateToken() { + $this->selector = bin2hex(\random_bytes(12)); + $this->token = bin2hex(\random_bytes(20)); + } + protected $data; + public function getData() { + if ($this->data === null) { + $this->data = (object) [ + 'ip' => 0, + 'token' => '', + 'time' => 0 + ]; + if ($this->manager->folder('data')->exists($this->filename)) { + $this->data = $this->manager->folder('data')->load($this->filename); + $this->data->time = Carbon::parse($this->data->time); + } + } + } + protected $ip; + public function getIp(Request $request) { + if ($this->ip === null) { + $this->ip = $request->getHeader('host')[0]; + } + return $this->ip; + } + + protected $is_logged_in; + public function checkAuth(Request $request): bool { + if ($this->is_logged_in === null) { + $this->loadCookie(); + if ($this->selector === null) { + $this->is_logged_in = false; + return false; + } + $this->getIp($request); + $this->getData(); + + if ($this->data->ip != $this->ip) { + $this->is_logged_in = false; + return false; + } + if ($this->data->token != implode(':', [$this->selector, $this->token])) { + $this->is_logged_in = false; + return false; + } + $now = Carbon::now(); + if ($this->data->time->copy()->addSeconds($this->time_limit)->diffInSeconds($now->copy()) < 0) { + $this->is_logged_in = false; + } + $this->is_logged_in = true; + } + return $this->is_logged_in; + } + public function login(Request $request): bool { + $post = $request->getParsedBody(); + if (!password_verify($post['clave'], $this->password)) { + return false; + } + $this->generateToken(); + $this->getIp($request); + $time = Carbon::now(); + $data = [ + 'ip' => $this->ip, + 'token' => implode(':', [$this->selector, $this->token]), + 'time' => $time->format('Y-m-d H:i') + ]; + $this->manager->folder('data')->save($this->filename, $data); + $this->saveCookie(); + $this->is_logged_in = true; + return true; + } +} diff --git a/composer.json b/composer.json index be18e64..9d9866f 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "tuupola/slim-basic-auth": "^3.2", "mustangostang/spyc": "^0.6.3", "nette/mail": "^3.1", - "nesbot/carbon": "^2.32" + "nesbot/carbon": "^2.32", + "vlucas/phpdotenv": "^4.1" }, "require-dev": { "phpunit/phpunit": "^8.5", diff --git a/provm/common/Basic/Controller.php b/provm/common/Basic/Controller.php index 04a23ab..b153e8a 100644 --- a/provm/common/Basic/Controller.php +++ b/provm/common/Basic/Controller.php @@ -11,7 +11,7 @@ abstract class Controller implements ControllerInterface { ->withHeader('Content-Type', 'application/json') ->withStatus(201); } - public function withRedirect(string $uri): Response { + public function withRedirect(Response $response, string $uri): Response { return $response ->withHeader('Location', $uri) ->withStatus(303); diff --git a/provm/common/Service/Filemanager.php b/provm/common/Service/Filemanager.php index b73feca..d00883b 100644 --- a/provm/common/Service/Filemanager.php +++ b/provm/common/Service/Filemanager.php @@ -30,9 +30,12 @@ class Filemanager { public function folder(string $name) { return new Filemanager($this->filesystem, $this->folders[$name]); } + public function exists(string $filename) { + return $this->filesystem->exists($this->fullPath($filename)); + } public function load(string $filename) { $filename = $this->fullPath($filename); - if (!$this->filesystem->exists($filename)) { + if (!$this->exists($filename)) { return false; } $file = new \SplFileInfo($filename); diff --git a/public/assets/styles/main.css b/public/assets/styles/main.css index 72728eb..14c580e 100644 --- a/public/assets/styles/main.css +++ b/public/assets/styles/main.css @@ -20,7 +20,17 @@ html { padding-left: 0 !important; } +#page_container { + display: flex; + flex-direction: column; + height: 100%; +} +.content { + flex: 1 0 auto; +} + footer { + flex: none; color: white; height: 260px; font-family: Roboto; diff --git a/public/index.php b/public/index.php index e952974..12ff1e5 100644 --- a/public/index.php +++ b/public/index.php @@ -1,4 +1,6 @@ + 2c579161cd33d9b2d3dd7791:b6936fbd9f2f1403558af3e5bc5330188af9a03e +time: 2020-04-07 16:20 diff --git a/resources/routes/router.php b/resources/routes/router.php index 8f1d32f..f7b9dfe 100644 --- a/resources/routes/router.php +++ b/resources/routes/router.php @@ -1,7 +1,7 @@ group('/admin', function($app) { } $app->get('[/]', Admin::class); -}); +})->add($app->getContainer()->get(ProVM\NotariaRaby\Common\Middleware\Auth::class)); diff --git a/resources/routes/web/admin/clave.php b/resources/routes/web/admin/clave.php new file mode 100644 index 0000000..31c8d89 --- /dev/null +++ b/resources/routes/web/admin/clave.php @@ -0,0 +1,7 @@ +group('/clave', function($app) { + $app->get('[/]', Clave::class); + $app->post('[/]', [Clave::class, 'do_edit']); +}); diff --git a/resources/routes/web/admin/login.php b/resources/routes/web/admin/login.php new file mode 100644 index 0000000..7a9588b --- /dev/null +++ b/resources/routes/web/admin/login.php @@ -0,0 +1,7 @@ +group('/login', function($app) { + $app->get('[/]', Login::class); + $app->post('[/]', [Login::class, 'do_login']); +}); diff --git a/resources/views/admin/clave.blade.php b/resources/views/admin/clave.blade.php new file mode 100644 index 0000000..9ecfbaf --- /dev/null +++ b/resources/views/admin/clave.blade.php @@ -0,0 +1,88 @@ +@extends('admin.layout.base') + +@section('content') +
+

Cambiar Clave

+
+
+ + +
+
+ + +
+ +
+
    +
    +
    +
      +
      +
      +
      +@endsection + +@push('scripts') + +@endpush diff --git a/resources/views/admin/login.blade.php b/resources/views/admin/login.blade.php index 8db5721..029ac69 100644 --- a/resources/views/admin/login.blade.php +++ b/resources/views/admin/login.blade.php @@ -1,11 +1,18 @@ -@extends('admin.base') +@extends('admin.layout.base') @section('content') -
      -
      - - -
      - -
      +
      +
      +
      +
      +

      Ingresar

      +
      + + +
      + +
      +
      +
      +
      @endsection diff --git a/resources/views/home/indice.blade.php b/resources/views/home/indice.blade.php index 973e4fe..dee3668 100644 --- a/resources/views/home/indice.blade.php +++ b/resources/views/home/indice.blade.php @@ -2,7 +2,7 @@
      -
      +
      ÍNDICES EN LÍNEA
      diff --git a/resources/views/layout/base.blade.php b/resources/views/layout/base.blade.php index 7713b59..fec9362 100644 --- a/resources/views/layout/base.blade.php +++ b/resources/views/layout/base.blade.php @@ -4,7 +4,9 @@
      @include('layout.header') - @yield('page_content') +
      + @yield('page_content') +
      @include('layout.footer')
      diff --git a/resources/views/layout/menu.blade.php b/resources/views/layout/menu.blade.php index fd93a6a..7374bc6 100644 --- a/resources/views/layout/menu.blade.php +++ b/resources/views/layout/menu.blade.php @@ -6,10 +6,10 @@ NOTARÍA - + SERVICIOS - + CONSULTAS diff --git a/vendor.tar b/vendor.tar new file mode 100644 index 0000000..238cf07 Binary files /dev/null and b/vendor.tar differ diff --git a/vendor.tar.gz b/vendor.tar.gz new file mode 100644 index 0000000..03eb2d1 Binary files /dev/null and b/vendor.tar.gz differ