diff --git a/meta/definitions/authorize.php b/meta/definitions/authorize.php index dbaa885..571fa24 100644 --- a/meta/definitions/authorize.php +++ b/meta/definitions/authorize.php @@ -2,20 +2,21 @@ use Lean\Factory\HttpFactoryInterface; -use Ulmus\User\{Authorize\HeaderAuthentication, +use Ulmus\User\{ + Authorize\HeaderAuthentication, Entity, Lib\Authenticate, Lib\Authorize, Middleware\AuthenticationMiddleware, Middleware\HeaderAuthenticationMiddleware, Middleware\PostRequestAuthenticationMiddleware, - Authorize\PostRequestAuthentication}; - -use Picea\Picea; + Authorize\PostRequestAuthentication +}; use Storage\{ Cookie, Session }; - use Psr\Container\ContainerInterface; +use Picea\Picea; + use function DI\{get, autowire, create}; return [ @@ -38,8 +39,9 @@ return [ 'authorize.error' => function(ContainerInterface $c) { return function(array $errorData) use ($c) { return $c->get(HttpFactoryInterface::class)::createJsonResponse($errorData + [ + 'api.error' => "Authorization failed", - 'api.datetime' => (new \DateTime)->format(\DateTime::ISO8601), + 'api.datetime' => (new \DateTime)->format(\DateTime::ATOM), ], 403); }; }, diff --git a/meta/definitions/event.php b/meta/definitions/event.php index 455890a..5cfa378 100644 --- a/meta/definitions/event.php +++ b/meta/definitions/event.php @@ -1,8 +1,6 @@ autowire(Event\EventManager::class), @@ -25,6 +26,7 @@ return [ Event\EventDefinition::class => function($c) { $extension = $c->has(\Picea\Extension\UrlExtension::class) ? $c->get(\Picea\Extension\UrlExtension::class) : null; + $user = $c->get(UserInterface::class); return new Event\EventDefinition([ new class($extension) implements RoutingCompileRoutes { @@ -40,7 +42,12 @@ return [ } }, - new class() implements RoutingMapRoutes { + new class($user) implements RoutingMapRoutes { + + public function __construct( + protected UserInterface $user + ) {} + public function execute(Routing $routing, ContainerInterface $container, ServerRequestInterface & $request, Route $attribute) : void { $class = $attribute->class; @@ -54,7 +61,7 @@ return [ $securityHandler = $container->get(SecurityHandler::class); if ( $redirect = $securityHandler->verify($class, $method) ) { - if ( empty($object->user) || ! $object->user->logged ) { + if (! $this->user->loggedIn() ) { if ($container->has(Session::class)) { $container->get(Session::class)->set('redirectedFrom', (string)$request->getUri()); } @@ -64,8 +71,8 @@ return [ } } - if ( $securityHandler->isLocked($class, $method) && $container->has(Taxus::class) && $container->has(SecurityHandler::class) ) { - if ( $forbidden = $container->get(SecurityHandler::class)->taxus($class, $method, $object->user ?? null) ) { + if ( $securityHandler->isLocked($class, $method) && $container->has(Taxus::class)) { + if ( $forbidden = $securityHandler->taxus($class, $method, $this->user) ) { $routing->response = $forbidden; return; diff --git a/meta/definitions/http.php b/meta/definitions/http.php index 74a5ff1..cee0964 100644 --- a/meta/definitions/http.php +++ b/meta/definitions/http.php @@ -1,6 +1,9 @@ function(ContainerInterface $c, Picea $picea) { return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml("lean/error/500", []), 500); - } + }, + + ThrowableHandlerInterface::class => autowire(ThrowableHandler::class), + NotFoundDecoratorInterface::class => autowire(NotFoundDecorator::class), ]; diff --git a/meta/definitions/orm.php b/meta/definitions/orm.php index 5fcec93..d272f3b 100644 --- a/meta/definitions/orm.php +++ b/meta/definitions/orm.php @@ -11,8 +11,12 @@ return [ ]), AdapterProxy::class => function (Psr\Container\ContainerInterface $c) { - return new AdapterProxy( - $c->get(ConnectionAdapter::class), - ); + $proxy = new AdapterProxy(); + + $autoload = $c->get(\Lean\Lean::class)->getConnectionAdapters(); + + $proxy->push($autoload); + + return $proxy; }, ]; diff --git a/meta/definitions/software.php b/meta/definitions/software.php index 31f329f..aaff563 100644 --- a/meta/definitions/software.php +++ b/meta/definitions/software.php @@ -66,20 +66,14 @@ return [ 'routes' => [], 'cronard' => [], - - 'taxus' => [ - 'is_dev' => [ ' dev' => "Is a developper of this application or has the same rights" ], - 'is_admin' => [ 'admin' => "Can manage almost everything in this application."], - 'is_moderator' => [ 'moderator' => "Can moderate this application."], - 'is_user' => [ 'user' => "Is an authenticated user."], - 'is_anonymous' => [ 'anonymous' => "Is an anonymous user."], - ], ], 'lean.autoload' => add([ Lean::class, ]), + \Lean\Factory\HttpFactoryInterface::class => autowire(\Lean\Factory\HttpFactory::class), + Lean::class => autowire(Lean::class), JavascriptMiddleware::class => create(JavascriptMiddleware::class), diff --git a/src/Application.php b/src/Application.php index 424c727..6fca8a4 100644 --- a/src/Application.php +++ b/src/Application.php @@ -22,6 +22,8 @@ class Application public array $entities; + public array $connectionAdapters; + public array $events; public array $tellJson; @@ -68,6 +70,7 @@ class Application if (is_array($ulmus = $this->data['ulmus'] ?? false)) { if ($ulmus['entities'] ?? false) { $this->entities = $ulmus['entities']; + $this->connectionAdapters = $ulmus['adapters'] ?? []; } } diff --git a/src/ApplicationStrategy.php b/src/ApplicationStrategy.php index 325ee74..f0de3e8 100644 --- a/src/ApplicationStrategy.php +++ b/src/ApplicationStrategy.php @@ -3,63 +3,33 @@ namespace Lean; use League\Route\Strategy; - use League\Route\Http\Exception\NotFoundException; -use Picea\Asset\Asset; +use Lean\ApplicationStrategy\NotFoundDecoratorInterface; +use Lean\ApplicationStrategy\ThrowableHandlerInterface; +use Lean\Factory\HttpFactoryInterface; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; -use Picea\Picea; use Psr\Http\Server\RequestHandlerInterface; use function DI\get; class ApplicationStrategy extends Strategy\ApplicationStrategy { - public const ASSET_TRIGGER_UPDATE = [ - "js", "mjs", "manifest", "webmanifest", "css", "png", "ico", - "jpg", "jpeg", "gif", "webp", "woff", "woff2", "eot", "svg", - "ttf" - ]; - public function __construct( - protected Picea $picea, - protected ContainerInterface $di, - ) {} + ContainerInterface $di, + ) { + $this->setContainer($di); + } public function getNotFoundDecorator(NotFoundException $exception): MiddlewareInterface { - return new class($this->picea, $this->di) implements MiddlewareInterface { + return $this->getContainer()->get(NotFoundDecoratorInterface::class); + } - public function __construct( - protected Picea $picea, - protected ContainerInterface $di, - ) { } + public function getThrowableHandler(): MiddlewareInterface + { + return $this->getContainer()->get(ThrowableHandlerInterface::class); - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - if (php_sapi_name() !== 'cli' and ! defined('STDIN')) { - return $this->throw404($request); - } - - return $handler->handle($request);; - } - - public function throw404(ServerRequestInterface $request) : ResponseInterface - { - if ( getenv('DEBUG') && $this->di->has(\Picea\Asset\Asset::class) ) { - $params = $request->getServerParams(); - - $scpName = basename(explode('?', $params['REQUEST_URI'] ?? "", 2)[0]); - list(, $ext) = array_pad(explode('.', $scpName), 2, null); - - if ($ext && in_array($ext, ApplicationStrategy::ASSET_TRIGGER_UPDATE)) { - $this->di->get(\Picea\Asset\Asset::class)->launchInstall(); - } - } - - return $this->di->get('error.404'); - } - }; } } \ No newline at end of file diff --git a/src/ApplicationStrategy/NotFoundDecorator.php b/src/ApplicationStrategy/NotFoundDecorator.php new file mode 100644 index 0000000..8ce628f --- /dev/null +++ b/src/ApplicationStrategy/NotFoundDecorator.php @@ -0,0 +1,62 @@ +throw404($request); + } + + return $handler->handle($request); + } + + public function throw404(ServerRequestInterface $request) : ResponseInterface + { + return $this->checkAssetTrigger($request) ?: $this->httpFactory->createHtmlResponse($this->picea->renderHtml("lean/error/404", [], $this), 404); + } + + protected function checkAssetTrigger(ServerRequestInterface $request) : false|ResponseInterface + { + if (getenv('DEBUG') && $this->container->has(\Picea\Asset\Asset::class)) { + $params = $request->getServerParams(); + + $scpName = basename(explode('?', $params['REQUEST_URI'] ?? "", 2)[0]); + list(, $ext) = array_pad(explode('.', $scpName), 2, null); + + if ($ext && in_array($ext, static::ASSET_TRIGGER_UPDATE)) { + $this->container->get(\Picea\Asset\Asset::class)->launchInstall(); + + return $this->httpFactory->createTextResponse("Asset updated"); + } + } + + return false; + } +} \ No newline at end of file diff --git a/src/ApplicationStrategy/NotFoundDecoratorInterface.php b/src/ApplicationStrategy/NotFoundDecoratorInterface.php new file mode 100644 index 0000000..530c657 --- /dev/null +++ b/src/ApplicationStrategy/NotFoundDecoratorInterface.php @@ -0,0 +1,10 @@ +handle($request); + } catch (Throwable $e) { + throw $e; + } + } +} \ No newline at end of file diff --git a/src/ApplicationStrategy/ThrowableHandlerInterface.php b/src/ApplicationStrategy/ThrowableHandlerInterface.php new file mode 100644 index 0000000..1ebdc54 --- /dev/null +++ b/src/ApplicationStrategy/ThrowableHandlerInterface.php @@ -0,0 +1,10 @@ +renderJson( - $data - ); - } - elseif ( is_array($data) ) { - var_export($data); + if (! $data instanceof \Stringable) { + if ($data instanceof \JsonSerializable) { + return $this->renderJson( + $data + ); + } + elseif (is_iterable($data) || is_object($data)) { + return $this->renderText(var_export($data, true)); + } } return $this->renderText( diff --git a/src/Event/RoutingMapRoutes.php b/src/Event/RoutingMapRoutes.php index e448574..eda90cf 100644 --- a/src/Event/RoutingMapRoutes.php +++ b/src/Event/RoutingMapRoutes.php @@ -6,6 +6,7 @@ use Lean\Routing; use Notes\Route\Attribute\Method\Route; use Psr\Container\ContainerInterface; use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface }; +use Ulmus\User\Entity\UserInterface; interface RoutingMapRoutes { public function execute(Routing $routing, ContainerInterface $container, ServerRequestInterface & $request, Route $attribute) : void; diff --git a/src/Kernel.php b/src/Kernel.php index e427592..9b18038 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -73,7 +73,9 @@ class Kernel { $path = getenv("PROJECT_PATH") . DIRECTORY_SEPARATOR . getenv($envkey); if (getenv('DEBUG') && ! file_exists($path)) { - mkdir($path, 0755, true); + if (false === mkdir($path, 0755, true)) { + throw new \Exception(sprintf("Folder '%s' could not be created", $path)); + } } static::putenv($name, realpath($path)); @@ -155,6 +157,7 @@ class Kernel { # Must be removed from KERNEL ! $this->container->has('ulmus.caching') and ( Ulmus::$cache = $this->container->get('ulmus.caching') ); + # $this->container->has(AdapterProxy::class) and ( $ ) return $this; } diff --git a/src/Lean.php b/src/Lean.php index 6bd50ba..32fc06b 100644 --- a/src/Lean.php +++ b/src/Lean.php @@ -77,37 +77,42 @@ class Lean public function getRoutable() : array { - return array_merge(...array_map(fn($app) => $app->routes ?? [], $this->applications)); + return array_merge(...array_map(fn(Application $app) => $app->routes ?? [], $this->applications)); } public function getCronard() : array { - return array_merge(...array_map(fn($app) => $app->cronard ?? [], $this->applications)); + return array_merge(...array_map(fn(Application $app) => $app->cronard ?? [], $this->applications)); } public function getCLI() : array { - return array_merge(...array_map(fn($app) => $app->cli ?? [], $this->applications)); + return array_merge(...array_map(fn(Application $app) => $app->cli ?? [], $this->applications)); } public function getEvents() : array { - return array_merge(...array_map(fn($app) => $app->events ?? [], $this->applications)); + return array_merge(...array_map(fn(Application $app) => $app->events ?? [], $this->applications)); } public function getTaxusPrivileges() : array { - return array_merge(...array_map(fn($app) => $app->taxus ?? [], $this->applications)); + return array_merge(...array_map(fn(Application $app) => $app->taxus ?? [], $this->applications)); } public function getEntities() : array { - return array_merge(...array_map(fn($app) => $app->entities ?? [], $this->applications)); + return array_merge(...array_map(fn(Application $app) => $app->entities ?? [], $this->applications)); + } + + public function getConnectionAdapters() : array + { + return array_merge(...array_map(fn(Application $app) => $app->connectionAdapters ?? [], $this->applications)); } public function getViewPaths() : array { - $list = array_merge(...array_map(fn($app) => $app->views ?? [], $this->applications)); + $list = array_merge(...array_map(fn(Application $app) => $app->views ?? [], $this->applications)); $this->verifyPathList($list); @@ -118,7 +123,7 @@ class Lean public function getAssetPaths() : array { - $list = array_merge(...array_map(fn($app) => $app->piceaAssets ?? [], $this->applications)); + $list = array_merge(...array_map(fn(Application $app) => $app->piceaAssets ?? [], $this->applications)); $this->verifyPathList($list); @@ -140,11 +145,11 @@ class Lean { switch($reader) { case "php": - $list = array_merge(...array_map(fn($app) => $app->tellPhp ?? [], $this->applications)); + $list = array_merge(...array_map(fn(Application $app) => $app->tellPhp ?? [], $this->applications)); break; case "json": - $list = array_merge(...array_map(fn($app) => $app->tellJson ?? [], $this->applications)); + $list = array_merge(...array_map(fn(Application $app) => $app->tellJson ?? [], $this->applications)); break; }