Diff #4 - trunk/share/HttpControllers/Webapp/AdminPanel.php
4,145 bytes
|
|
January 20, 2025 at 08:20
|
Diff
Index: AdminPanel.php
--- AdminPanel.php (nonexistent) +++ AdminPanel.php (revision 4) @@ -0,0 +1,149 @@ +<?php +declare(strict_types = 1); + +namespace App\HttpControllers\Webapp; + +use Apex\Svc{App, View, Db}; +use App\Webapp\AdminProfiles; +use Apex\Armor\Armor; +use Apex\Armor\Exceptions\ArmorProfileValidationException; +use Nyholm\Psr7\Response; +use Psr\Http\Message{ServerRequestInterface, ResponseInterface}; +use Psr\Http\Server{MiddlewareInterface, RequestHandlerInterface}; + +/** + * Http Controller - admin_panel + / +class AdminPanel implements MiddlewareInterface +{ + + #[Inject(View::class)] + private View $view; + + #[Inject(Db::class)] + private Db $db; + + #[Inject(AdminProfiles::class)] + private AdminProfiles $profiles; + + #[Inject(Armor::class)] + private Armor $armor; + + /** + * Process request + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $app): ResponseInterface + { + + // Initialize + $app->setArea('admin', true); + $this->armor->loadPolicy('admin'); + + // Check for non-standard path + $nonstd_path = null; + if (!preg_match("/^admin\//", trim($app->getPath(), '/'))) { + $parts = explode('/', trim($app->getPath(), '/')); + $nonstd_path = '/' . array_shift($parts) . '/'; + $app->setPath('/admin/' . implode('/', $parts)); + } + + // Check auth + if (!$session = $this->profiles->checkAuth()) { + $this->checkFirstAdmin($app, $nonstd_path); + } + + // Assign profile to view + if (null !== $app->getUser()) { + $profile = $app->getUser()->toDisplayArray(); + $this->view->assign('profile', $profile); + } + + // Check acl + if (!$this->checkAcl($app->getUuid(), $app->getPath())) { + $html = $this->view->render('admin/404'); + return new Response(404, [], $html); + } + + // Render template via auto-routing based on URI being viewed + $html = $this->view->render(); + + // Check for non-standard path + if ($nonstd_path !== null) { + $html = str_replace("/admin/", $nonstd_path, $html); + } + + // Create response + $response = new Response( + body: $html + ); + + // Return + return $response; + } + + /** + * Check first admin + */ + private function checkFirstAdmin(App $app, ?string $nonstd_path = null):void + { + + // Check number of admins + if ($id = $this->db->getField("SELECT uuid FROM admin LIMIT 1")) { + $this->view->setTemplateFile('admin/login'); + return; + } else { + $this->view->setTemplateFile('admin/create_first_admin'); + } + + // Create admin, if needed + if ($app->getAction() == 'create') { + + // Create admin + if (!$user = $this->profiles->create()) { + return; + } + + // Set admin panel homepage template + $app->setUser($user); + $this->view->setTemplateFile('admin/index', true); + $this->view->assign('profile', $user->toDisplayArray()); + } + } + + /** + * Check ACL + */ + private function checkAcl(string $uuid, string $path):bool + { + + // Ensure sub-menu being viewed + if (!preg_match("/admin\/(.+?)\/(.+)$/", trim($path, '/'), $match)) { + return true; + } + $parent = $match[1]; + $alias = $match[2]; + + // Check if we have allowed menus + if (!$count = $this->db->getField("SELECT count() FROM cms_menus_acl WHERE area = 'admin' AND uuid = %s", $uuid)) { + return true; + } elseif ($count == 0) { + return true; + } + + // Check for menu + if (!$row = $this->db->getRow("SELECT * FROM cms_menus WHERE area = 'admin' AND parent = %s AND alias = %s", $parent, $alias)) { + return true; + } + + // Check if menu allowed + if (!$row = $this->db->getField("SELECT * FROM cms_menus_acl WHERE area = 'admin' AND uuid = %s AND parent = %s AND alias = %s", $uuid, $parent, $alias)) { + return false; + } + + // Return + return true; + } +} + + +
Full Code
<?php declare(strict_types = 1);
namespace App\HttpControllers\Webapp;
use Apex\Svc{App, View, Db}; use App\Webapp\AdminProfiles; use Apex\Armor\Armor; use Apex\Armor\Exceptions\ArmorProfileValidationException; use Nyholm\Psr7\Response; use Psr\Http\Message{ServerRequestInterface, ResponseInterface}; use Psr\Http\Server{MiddlewareInterface, RequestHandlerInterface};
/** * Http Controller - admin_panel */ class AdminPanel implements MiddlewareInterface {
#[Inject(View::class)]
private View $view;
#[Inject(Db::class)]
private Db $db;
#[Inject(AdminProfiles::class)]
private AdminProfiles $profiles;
#[Inject(Armor::class)]
private Armor $armor;
/**
* Process request
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $app): ResponseInterface
{
// Initialize
$app->setArea('admin', true);
$this->armor->loadPolicy('admin');
// Check for non-standard path
$nonstd_path = null;
if (!preg_match("/^admin\//", trim($app->getPath(), '/'))) {
$parts = explode('/', trim($app->getPath(), '/'));
$nonstd_path = '/' . array_shift($parts) . '/';
$app->setPath('/admin/' . implode('/', $parts));
}
// Check auth
if (!$session = $this->profiles->checkAuth()) {
$this->checkFirstAdmin($app, $nonstd_path);
}
// Assign profile to view
if (null !== $app->getUser()) {
$profile = $app->getUser()->toDisplayArray();
$this->view->assign('profile', $profile);
}
// Check acl
if (!$this->checkAcl($app->getUuid(), $app->getPath())) {
$html = $this->view->render('admin/404');
return new Response(404, [], $html);
}
// Render template via auto-routing based on URI being viewed
$html = $this->view->render();
// Check for non-standard path
if ($nonstd_path !== null) {
$html = str_replace("/admin/", $nonstd_path, $html);
}
// Create response
$response = new Response(
body: $html
);
// Return
return $response;
}
/**
* Check first admin
*/
private function checkFirstAdmin(App $app, ?string $nonstd_path = null):void
{
// Check number of admins
if ($id = $this->db->getField("SELECT uuid FROM admin LIMIT 1")) {
$this->view->setTemplateFile('admin/login');
return;
} else {
$this->view->setTemplateFile('admin/create_first_admin');
}
// Create admin, if needed
if ($app->getAction() == 'create') {
// Create admin
if (!$user = $this->profiles->create()) {
return;
}
// Set admin panel homepage template
$app->setUser($user);
$this->view->setTemplateFile('admin/index', true);
$this->view->assign('profile', $user->toDisplayArray());
}
}
/**
* Check ACL
*/
private function checkAcl(string $uuid, string $path):bool
{
// Ensure sub-menu being viewed
if (!preg_match("/admin\/(.+?)\/(.+)$/", trim($path, '/'), $match)) {
return true;
}
$parent = $match[1];
$alias = $match[2];
// Check if we have allowed menus
if (!$count = $this->db->getField("SELECT count(*) FROM cms_menus_acl WHERE area = 'admin' AND uuid = %s", $uuid)) {
return true;
} elseif ($count == 0) {
return true;
}
// Check for menu
if (!$row = $this->db->getRow("SELECT * FROM cms_menus WHERE area = 'admin' AND parent = %s AND alias = %s", $parent, $alias)) {
return true;
}
// Check if menu allowed
if (!$row = $this->db->getField("SELECT * FROM cms_menus_acl WHERE area = 'admin' AND uuid = %s AND parent = %s AND alias = %s", $uuid, $parent, $alias)) {
return false;
}
// Return
return true;
}
}