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": {
"ext-pdo": "*",
"ext-http": "*",
"ext-json": "*"
"ext-pdo": "*"
},
"autoload": {
"psr-4": {

View file

@ -7,14 +7,6 @@ create table if not exists seoData
)
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
(
id int(255) auto_increment not null unique primary key,
@ -35,16 +27,3 @@ create table if not exists data
datatype enum ('content', 'form')
)
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\Setup;
use Venom\Helper\URLHelper;
use Venom\Venom;
require_once '../vendor/autoload.php';
session_start();
Setup::loadConfig(URLHelper::getInstance()->isAdminUrl());
Setup::loadConfig(false);
Setup::loadLanguage();
$config = Config::getInstance();
@ -23,4 +21,4 @@ if ($config->isDevMode()) {
$venom = new Venom();
Setup::loadRouters($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;
private array $arguments = [];
private array $post = [];
public function __construct()
{
@ -17,7 +16,6 @@ class ArgumentHandler
}
foreach ($_POST as $key => $item) {
$this->arguments[htmlspecialchars($key)] = htmlspecialchars($item);
$this->post[htmlspecialchars($key)] = htmlspecialchars($item);
}
}
@ -43,14 +41,4 @@ class ArgumentHandler
{
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;
use Venom\Core\ArgumentHandler;
use Venom\Core\DatabaseHandler;
/**
* Class MetaGenerator
* @package Venom\Helper
*/
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;
}
public function isAdminUrl(): bool
{
return strpos($this->parsedUrl, '/admin/') === 0;
}
}

View file

@ -4,124 +4,11 @@
namespace Venom\Models;
use Venom\Core\DatabaseHandler;
class User
{
public const ADMIN_ROLE = 'ROLE_ADMIN';
public const GUEST_ROLE = 'ROLE_GUEST';
private string $username = 'GUEST';
private string $email = 'GUEST';
private string $password = '---';
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;
}
private string $username;
private string $password;
private string $salt;
private string $token;
private array $roles;
}

View file

@ -5,14 +5,9 @@ namespace Venom\Routing;
use Exception;
use Venom\Core\Config;
use Venom\Models\User;
use Venom\Security\Security;
class Router
{
public const DEFAULT_ROUTER = 'defaultRouter';
public const ADMIN_ROUTER = 'adminRouter';
protected string $id = 'defaultRouter';
protected int $version;
protected string $prefix = '';
@ -71,12 +66,6 @@ class Router
$subRouteFound = isset($this->routes[$url]['routes'][$subRoute]);
$methodFound = isset($this->routes[$url]['routes'][$subRoute][$method]);
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 [
'cl' => $this->routes[$url]['cl'],
'fnc' => $this->routes[$url]['routes'][$subRoute][$method],

View file

@ -4,50 +4,10 @@
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 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 checkUsername(): bool;
public function checkPassword(): bool;
public function checkCredentials(): bool;
public function login(): bool;

View file

@ -3,20 +3,10 @@
namespace Venom\Security;
use \RuntimeException;
use Venom\Core\Config;
use Venom\Models\User;
class Security
{
private static ?Security $instance = null;
private ?User $user;
public function __construct()
{
$this->user = new User();
$this->user->loadUser();
}
public static function get(): Security
{
@ -26,39 +16,15 @@ class Security
return self::$instance;
}
/* @todo implement logic */
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;
}
public function login(): void
/* @todo implement logic */
public function hasRoles(array $roles): bool
{
if ($this->user->isLoaded()) {
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();
return true;
}
}

View file

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

View file

@ -3,7 +3,7 @@
namespace Venom\Views;
use \RuntimeException;
use RuntimeException;
use Venom\Core\DatabaseHandler;
use Venom\Models\DataModel;
@ -87,8 +87,8 @@ class DataLoader
private function generateID(string $id = ''): string
{
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\Config;
use Venom\Helper\MetaGenerator;
use Venom\Venom;
class VenomRenderer
{
private Venom $venom;
private ?RenderController $controller;
private ?MetaGenerator $metaGenerator;
private string $templateData = '';
private array $vars = [];
private string $baseTemplate = '';
@ -86,7 +84,7 @@ class VenomRenderer
return $this->vars[$name];
}
public function deleteVar($name): void
public function deleteVar($name)
{
unset($this->vars[$name]);
}
@ -95,16 +93,7 @@ class VenomRenderer
{
$this->controller = $controller;
$data = Config::getInstance()->getRenderer();
$theme = $data->theme;
$base = $data->baseFile ?? 'base';
$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 . '/';
$this->baseTemplate = $data->baseFile . '.php' ?? 'base.php';
$this->templateDir = __DIR__ . '/../../../tpl/' . $data->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>';
}