Compare commits

..

No commits in common. "dev" and "master" have entirely different histories.
dev ... master

22 changed files with 58 additions and 471 deletions

View file

@ -9,9 +9,7 @@
} }
], ],
"require": { "require": {
"ext-pdo": "*", "ext-pdo": "*"
"ext-http": "*",
"ext-json": "*"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View file

@ -7,14 +7,6 @@ create table if not exists seoData
) )
comment 'seo url mapping'; comment 'seo url mapping';
create table if not exists metaTagData
(
id int(255) auto_increment not null unique primary key,
content JSON not null,
isActive tinyint(1) default 1 null
)
comment 'Meta Tag File';
create table if not exists language create table if not exists language
( (
id int(255) auto_increment not null unique primary key, id int(255) auto_increment not null unique primary key,
@ -35,16 +27,3 @@ create table if not exists data
datatype enum ('content', 'form') datatype enum ('content', 'form')
) )
comment 'DataLoader File'; comment 'DataLoader File';
create table if not exists users
(
id int(255) auto_increment not null unique primary key,
username varchar(255) not null unique,
email varchar(255) not null,
password varchar(255) not null,
token varchar(255) not null,
salt varchar(255) not null,
roles text default 'ROLE_GUEST' not null,
isActive tinyint(1) default 1 null
)
comment 'User File';

7
public/admin/.htaccess Normal file
View file

@ -0,0 +1,7 @@
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (/[^.]*|\.)$ [NC]
RewriteRule .* index.php [L]

24
public/admin/index.php Normal file
View file

@ -0,0 +1,24 @@
<?php
use Venom\Core\Config;
use Venom\Core\Setup;
use Venom\Venom;
require_once '../../vendor/autoload.php';
Setup::loadConfig(true);
Setup::loadLanguage();
$config = Config::getInstance();
if ($config->isMaintenance()) {
echo 'Currently not available';
exit;
}
//if devMode is on show all errors!
if ($config->isDevMode()) {
error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
}
$venom = new Venom();
Setup::loadRouters($venom);
Setup::loadModules($venom);
$venom->run();

View file

@ -2,12 +2,10 @@
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Core\Setup; use Venom\Core\Setup;
use Venom\Helper\URLHelper;
use Venom\Venom; use Venom\Venom;
require_once '../vendor/autoload.php'; require_once '../vendor/autoload.php';
session_start(); Setup::loadConfig(false);
Setup::loadConfig(URLHelper::getInstance()->isAdminUrl());
Setup::loadLanguage(); Setup::loadLanguage();
$config = Config::getInstance(); $config = Config::getInstance();
@ -23,4 +21,4 @@ if ($config->isDevMode()) {
$venom = new Venom(); $venom = new Venom();
Setup::loadRouters($venom); Setup::loadRouters($venom);
Setup::loadModules($venom); Setup::loadModules($venom);
$venom->inject(); $venom->run();

View file

@ -1,22 +0,0 @@
* {
box-sizing: border-box;
}
html, body {
margin: 0;
font-size: 16px;
color: #fff;
background-color: #333;
font-family: sans-serif;
height: 100vh;
width: 100vw;
}
header {
font-size: 5vw;
cursor: pointer;
}
header:hover {
color: #ff0323;
}

View file

@ -1,35 +0,0 @@
<?php
namespace Venom\Admin;
use Venom\Helper\URLHelper;
use Venom\Views\RenderController;
use Venom\Views\VenomRenderer;
class AdminController implements RenderController
{
private string $tpl = 'default';
public function register(): bool
{
return true;
}
public function render(VenomRenderer $renderer): bool
{
if (URLHelper::getInstance()->getUrl() !== '/admin/') {
http_response_code(404);
$this->tpl = 'async';
}
return true;
}
public function getTemplate(): string
{
return $this->tpl;
}
}

View file

@ -1,37 +0,0 @@
<?php
namespace Venom\Admin;
use Venom\Admin\Routes\LoginRoute;
use Venom\Routing\Router;
use Venom\Venom;
class AdminRouterInit
{
public static function registerAdminRouters(Venom $venom): void
{
$router = new Router(Router::ADMIN_ROUTER, 1.0, '/admin/api');
$router->addRoutes(self::getRoutes());
$venom->addRouter(Router::ADMIN_ROUTER, $router);
}
public static function getRoutes(): array
{
return [
'/login' => [
'cl' => LoginRoute::class,
'roles' => ['ROLE_GUEST'],
'routes' => [
'*' => [
"POST" => 'login'
],
'1' => [
"GET" => 'handle'
]
]
]
];
}
}

View file

@ -1,30 +0,0 @@
<?php
namespace Venom\Admin\Routes;
use Venom\Core\ArgumentHandler;
use Venom\Routing\Route;
use Venom\Security\Security;
class LoginRoute implements Route
{
public function login(): bool
{
Security::get()->login();
return true;
}
public function handle($fnc): bool
{
if ($fnc === 'logout') {
Security::get()->logout();
$url = ArgumentHandler::get()->getPostItem('REDIRECT_TO', '/admin/');
header('Location: ' . $url);
die();
}
return true;
}
}

View file

@ -8,7 +8,6 @@ class ArgumentHandler
{ {
public static ?ArgumentHandler $instance = null; public static ?ArgumentHandler $instance = null;
private array $arguments = []; private array $arguments = [];
private array $post = [];
public function __construct() public function __construct()
{ {
@ -17,7 +16,6 @@ class ArgumentHandler
} }
foreach ($_POST as $key => $item) { foreach ($_POST as $key => $item) {
$this->arguments[htmlspecialchars($key)] = htmlspecialchars($item); $this->arguments[htmlspecialchars($key)] = htmlspecialchars($item);
$this->post[htmlspecialchars($key)] = htmlspecialchars($item);
} }
} }
@ -43,14 +41,4 @@ class ArgumentHandler
{ {
return isset($this->arguments[$key]); return isset($this->arguments[$key]);
} }
public function getPostItem(string $key, $default = null)
{
return $this->post[$key] ?? $default;
}
public function hasPostItem(string $key): bool
{
return isset($this->post[$key]);
}
} }

View file

@ -4,40 +4,11 @@
namespace Venom\Helper; namespace Venom\Helper;
use Venom\Core\ArgumentHandler;
use Venom\Core\DatabaseHandler;
/** /**
* Class MetaGenerator * Class MetaGenerator
* @package Venom\Helper * @package Venom\Helper
*/ */
class MetaGenerator class MetaGenerator
{ {
private array $container = [];
private string $id;
public function __construct()
{
$this->id = (string)ArgumentHandler::get()->getItem('metaId', '-1');
}
public function loadById(): void
{
if ($this->id === '-1') {
return;
}
$db = DatabaseHandler::get();
$data = $db->getOne('select content from metaTagData where id = :id', [':id' => $this->id]);
if ($data !== null) {
$this->container = json_decode($data->content ?? '', true);
$this->container = array_merge([], $this->container);
}
}
public function render(): void
{
foreach($this->container as $key => $value) {
echo '<meta name="'.$key.'" content="'.$value.'">';
}
}
} }

View file

@ -42,9 +42,4 @@ class URLHelper
{ {
return $url; return $url;
} }
public function isAdminUrl(): bool
{
return strpos($this->parsedUrl, '/admin/') === 0;
}
} }

View file

@ -4,124 +4,11 @@
namespace Venom\Models; namespace Venom\Models;
use Venom\Core\DatabaseHandler;
class User class User
{ {
public const ADMIN_ROLE = 'ROLE_ADMIN'; private string $username;
public const GUEST_ROLE = 'ROLE_GUEST'; private string $password;
private string $username = 'GUEST'; private string $salt;
private string $email = 'GUEST'; private string $token;
private string $password = '---'; private array $roles;
private string $salt = '---';
private string $token = '---';
private string $id = '-1';
private array $roles = [];
private bool $isLoaded = false;
public function hasRole(string $role): bool
{
return in_array($role, $this->roles, true);
}
public function loadUser(): bool
{
if (isset($_SESSION['userID']) || $this->username !== 'GUEST') {
// try to load user from id!
$user = DatabaseHandler::get()->getOne("SELECT * FROM users WHERE id = :id OR username = :name AND isActive = 1", [
':id' => $_SESSION['userID'],
':name' => $this->username
]);
if ($user !== null) {
$this->username = $user->username ?? '';
$this->email = $user->email ?? '';
$this->password = $user->password ?? '';
$this->token = $user->token ?? '';
$this->salt = $user->salt ?? '';
$this->id = $user->id ?? '-1';
$this->roles = explode(',', $user->roles ?? '');
$this->isLoaded = true;
return true;
}
}
return false;
}
public function getUsername(): string
{
return $this->username;
}
public function setUsername(string $username): void
{
$this->username = $username;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): void
{
$this->email = $email;
}
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): void
{
$this->password = $password;
}
public function getSalt(): string
{
return $this->salt;
}
public function setSalt(string $salt): void
{
$this->salt = $salt;
}
public function getToken(): string
{
return $this->token;
}
public function setToken(string $token): void
{
$this->token = $token;
}
public function getRoles(): array
{
return $this->roles;
}
public function setRoles(array $roles): void
{
$this->roles = $roles;
}
public function addRole($value): void
{
if (!in_array($value, $this->roles, true)) {
$this->roles[] = $value;
}
}
public function isLoaded(): bool
{
return $this->isLoaded;
}
public function getId(): string
{
return $this->id;
}
} }

View file

@ -5,14 +5,9 @@ namespace Venom\Routing;
use Exception; use Exception;
use Venom\Core\Config;
use Venom\Models\User;
use Venom\Security\Security;
class Router class Router
{ {
public const DEFAULT_ROUTER = 'defaultRouter';
public const ADMIN_ROUTER = 'adminRouter';
protected string $id = 'defaultRouter'; protected string $id = 'defaultRouter';
protected int $version; protected int $version;
protected string $prefix = ''; protected string $prefix = '';
@ -71,12 +66,6 @@ class Router
$subRouteFound = isset($this->routes[$url]['routes'][$subRoute]); $subRouteFound = isset($this->routes[$url]['routes'][$subRoute]);
$methodFound = isset($this->routes[$url]['routes'][$subRoute][$method]); $methodFound = isset($this->routes[$url]['routes'][$subRoute][$method]);
if ($routeAvailable && $subRouteFound && $methodFound) { if ($routeAvailable && $subRouteFound && $methodFound) {
if ((Config::getInstance()->getSecurity()->useSecurity || $this->id === self::ADMIN_ROUTER) && isset($this->routes[$url]['roles'])) {
$roles = $this->routes[$url]['roles'];
if (!in_array(User::GUEST_ROLE, $roles, true) && !Security::get()->hasRoles($roles)) {
return null;
}
}
return [ return [
'cl' => $this->routes[$url]['cl'], 'cl' => $this->routes[$url]['cl'],
'fnc' => $this->routes[$url]['routes'][$subRoute][$method], 'fnc' => $this->routes[$url]['routes'][$subRoute][$method],

View file

@ -4,50 +4,10 @@
namespace Venom\Security; namespace Venom\Security;
use Venom\Core\ArgumentHandler;
use Venom\Core\Config;
use Venom\Helper\URLHelper;
use Venom\Models\User;
/** /**
* Class that Login stupid via Password, Username * Class that Login stupid via Password, Username
*/ */
class BaseLogin implements Login class BaseLogin
{ {
private User $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function checkCredentials(): bool
{
$handler = ArgumentHandler::get();
return $handler->hasPostItem('USERNAME') && $handler->hasPostItem('PASSWORD');
}
public function redirect(): void
{
$url = ArgumentHandler::get()->getPostItem('REDIRECT_TO', URLHelper::getInstance()->getUrl());
header('Location: ' . $url);
die();
}
public function login(): bool
{
$sec = Config::getInstance()->getSecurity();
$this->user->setUsername(ArgumentHandler::get()->getPostItem('USERNAME'));
if (!$this->user->loadUser()) {
return false;
}
$secret = $sec->secret ?? 'venom';
$hashed = hash($sec->algo ?? 'SHA256', ArgumentHandler::get()->getPostItem('PASSWORD') . $secret . $this->user->getSalt());
if ($this->user->getPassword() === $hashed) {
$_SESSION['userID'] = $this->user->getId();
return true;
}
return false;
}
} }

View file

@ -10,6 +10,10 @@ interface Login
{ {
public function __construct(User $user); public function __construct(User $user);
public function checkUsername(): bool;
public function checkPassword(): bool;
public function checkCredentials(): bool; public function checkCredentials(): bool;
public function login(): bool; public function login(): bool;

View file

@ -3,20 +3,10 @@
namespace Venom\Security; namespace Venom\Security;
use \RuntimeException;
use Venom\Core\Config;
use Venom\Models\User;
class Security class Security
{ {
private static ?Security $instance = null; private static ?Security $instance = null;
private ?User $user;
public function __construct()
{
$this->user = new User();
$this->user->loadUser();
}
public static function get(): Security public static function get(): Security
{ {
@ -26,39 +16,15 @@ class Security
return self::$instance; return self::$instance;
} }
/* @todo implement logic */
public function hasRole(string $role): bool public function hasRole(string $role): bool
{ {
return $this->user->hasRole($role);
}
public function hasRoles(array $roles): bool
{
foreach ($roles as $role) {
if (!$this->user->hasRole($role)) {
return false;
}
}
return true; return true;
} }
public function login(): void /* @todo implement logic */
public function hasRoles(array $roles): bool
{ {
if ($this->user->isLoaded()) { return true;
throw new RuntimeException('Try to re-login!');
}
$sec = Config::getInstance()->getSecurity();
$login = new $sec->securityClass($this->user);
if ($login instanceof Login) {
if (!$login->checkCredentials() || !$login->login()) {
http_response_code(401);
}
$login->redirect();
}
}
public function logout(): void
{
unset($_SESSION['userID']);
$this->user = new User();
} }
} }

View file

@ -4,8 +4,6 @@
namespace Venom; namespace Venom;
use Venom\Admin\AdminController;
use Venom\Admin\AdminRouterInit;
use Venom\Core\ArgumentHandler; use Venom\Core\ArgumentHandler;
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Core\Module; use Venom\Core\Module;
@ -32,22 +30,13 @@ class Venom
Asset::get()->setRenderer($this->renderer); Asset::get()->setRenderer($this->renderer);
} }
public function inject(): void
{
$this->run();
}
public function run(): void public function run(): void
{ {
$arguments = ArgumentHandler::get(); $arguments = ArgumentHandler::get();
$arguments->setItem(ErrorHandler::ERROR_KEY, false); $arguments->setItem(ErrorHandler::ERROR_KEY, false);
$config = Config::getInstance();
if ($config->isAdmin()) {
$this->initAdmin();
}
// we need to load the current controller and the current start template. // we need to load the current controller and the current start template.
// after this we can start the renderer // after this we can start the renderer
if ($config->isRouterEnabled() || $config->isAdmin()) { if (Config::getInstance()->isRouterEnabled()) {
$status = $this->useRouter(); $status = $this->useRouter();
if ($status['found']) { if ($status['found']) {
if ($status['status']) { if ($status['status']) {
@ -59,32 +48,18 @@ class Venom
$registry = Registry::getInstance(); $registry = Registry::getInstance();
$registry->getLang()->initLang(); $registry->getLang()->initLang();
// if site is errored then dont load via SEO // if site is errored then dont load via SEO
if (!$config->isAdmin() && !$arguments->getItem(ErrorHandler::ERROR_KEY)) { if (!$arguments->getItem(ErrorHandler::ERROR_KEY)) {
$registry->getSeo()->loadSite(); $registry->getSeo()->loadSite();
} }
$this->renderer->init($this->findController()); $this->renderer->init($this->findController());
$this->renderer->render(); $this->renderer->render();
} }
public function initAdmin(): void
{
$this->controllers['adminCtrl'] = AdminController::class;
AdminRouterInit::registerAdminRouters($this);
ArgumentHandler::get()->setItem('cl', 'adminCtrl');
}
private function useRouter(): array private function useRouter(): array
{ {
$url = URLHelper::getInstance()->getUrl(); $url = URLHelper::getInstance()->getUrl();
$isAdmin = Config::getInstance()->isAdmin();
/** @var Router $router */ /** @var Router $router */
foreach ($this->routers as $key => $router) { foreach ($this->routers as $router) {
if ($isAdmin && $key !== Router::ADMIN_ROUTER) {
continue;
}
if (!$isAdmin && $key === Router::ADMIN_ROUTER) {
continue;
}
$route = $router->findRoute($url, $_SERVER['REQUEST_METHOD']); $route = $router->findRoute($url, $_SERVER['REQUEST_METHOD']);
$status = $router->tryFunctionCall($route); $status = $router->tryFunctionCall($route);
if ($route !== null) { if ($route !== null) {

View file

@ -3,7 +3,7 @@
namespace Venom\Views; namespace Venom\Views;
use \RuntimeException; use RuntimeException;
use Venom\Core\DatabaseHandler; use Venom\Core\DatabaseHandler;
use Venom\Models\DataModel; use Venom\Models\DataModel;
@ -87,8 +87,8 @@ class DataLoader
private function generateID(string $id = ''): string private function generateID(string $id = ''): string
{ {
if ($id === '') { if ($id === '') {
$id = bin2hex(random_bytes(32)); $id = bin2hex(random_bytes(16));
} }
return hash('SHA256', $id); return $id;
} }
} }

View file

@ -6,14 +6,12 @@ namespace Venom\Views;
use Venom\Core\ArgumentHandler; use Venom\Core\ArgumentHandler;
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Helper\MetaGenerator;
use Venom\Venom; use Venom\Venom;
class VenomRenderer class VenomRenderer
{ {
private Venom $venom; private Venom $venom;
private ?RenderController $controller; private ?RenderController $controller;
private ?MetaGenerator $metaGenerator;
private string $templateData = ''; private string $templateData = '';
private array $vars = []; private array $vars = [];
private string $baseTemplate = ''; private string $baseTemplate = '';
@ -86,7 +84,7 @@ class VenomRenderer
return $this->vars[$name]; return $this->vars[$name];
} }
public function deleteVar($name): void public function deleteVar($name)
{ {
unset($this->vars[$name]); unset($this->vars[$name]);
} }
@ -95,16 +93,7 @@ class VenomRenderer
{ {
$this->controller = $controller; $this->controller = $controller;
$data = Config::getInstance()->getRenderer(); $data = Config::getInstance()->getRenderer();
$theme = $data->theme; $this->baseTemplate = $data->baseFile . '.php' ?? 'base.php';
$base = $data->baseFile ?? 'base'; $this->templateDir = __DIR__ . '/../../../tpl/' . $data->theme . '/';
$this->metaGenerator = new MetaGenerator();
if (Config::getInstance()->isAdmin()) {
$base = 'base';
$theme = 'admin';
} else {
$this->metaGenerator->loadById();
}
$this->baseTemplate = $base . '.php';
$this->templateDir = __DIR__ . '/../../../tpl/' . $theme . '/';
} }
} }

View file

@ -1,19 +0,0 @@
<?php
use Venom\Models\User;
use \Venom\Security\Security;
if (!Security::get()->hasRole(User::ADMIN_ROLE)) {
?>
<form method="post" action="/admin/api/login">
<input type="text" name="USERNAME" placeholder="Username">
<input type="password" name="PASSWORD" placeholder="Password">
<input type="hidden" name="REDIRECT_TO" value="/admin/">
<input type="submit" value="Login">
</form>
<?php
echo 'Login!';
} else {
echo 'Admin Interface!';
echo '<a href="/admin/api/login/logout">Ausloggen</a>';
}