-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
44 changed files
with
2,162 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: PHP check syntax errors | ||
|
||
on: | ||
push: | ||
branches: [ "**" ] | ||
pull_request: | ||
branches: [ "master" ] | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: overtrue/[email protected] | ||
- uses: php-actions/phpcs@v1 | ||
with: | ||
php_version: 8.2 | ||
path: App/ | ||
standard: PSR12 | ||
args: "--runtime-set ignore_warnings_on_exit 1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
<?php | ||
|
||
namespace App; | ||
|
||
use App\Config\Configuration; | ||
use App\Core\HTTPException; | ||
use App\Core\IAuthenticator; | ||
use App\Core\DB\Connection; | ||
use App\Core\LinkGenerator; | ||
use App\Core\Request; | ||
use App\Core\Responses\RedirectResponse; | ||
use App\Core\Responses\Response; | ||
use App\Core\Router; | ||
|
||
/** | ||
* Class App | ||
* Main Application class | ||
* @package App | ||
*/ | ||
class App | ||
{ | ||
/** | ||
* @var Router | ||
*/ | ||
private $router; | ||
/** | ||
* @var Request | ||
*/ | ||
private Request $request; | ||
private LinkGenerator $linkGenerator; | ||
private ?IAuthenticator $auth; | ||
|
||
/** | ||
* App constructor | ||
*/ | ||
public function __construct() | ||
{ | ||
$this->router = new Router(); | ||
$this->request = new Request(); | ||
$this->linkGenerator = new LinkGenerator($this->request, $this->router); | ||
|
||
// Check if there is an authenticator | ||
if (defined('\\App\\Config\\Configuration::AUTH_CLASS')) { | ||
//$authClass = Configuration::AUTH_CLASS; | ||
$this->auth = new (Configuration::AUTH_CLASS)(); | ||
} else { | ||
$this->auth = null; | ||
} | ||
} | ||
|
||
/** | ||
* Runs the application | ||
* @throws \Exception | ||
*/ | ||
public function run() | ||
{ | ||
ob_start(); | ||
|
||
try { | ||
// get a controller and action from URL | ||
$this->router->processURL(); | ||
|
||
// inject app into Controller | ||
call_user_func([$this->router->getController(), 'setApp'], $this); | ||
|
||
// try to authorize action | ||
if ($this->router->getController()->authorize($this->router->getAction())) { | ||
// call appropriate method of the controller class | ||
$response = call_user_func([$this->router->getController(), $this->router->getAction()]); | ||
|
||
// return view to user | ||
if ($response instanceof Response) { | ||
$response->send(); | ||
} else { | ||
throw new \Exception("Action {$this->router->getFullControllerName()}::{$this->router->getAction()} didn't return an instance of Response."); | ||
} | ||
} else { | ||
if ($this->auth->isLogged() || !defined('\\App\\Config\\Configuration::LOGIN_URL')) { | ||
throw new HTTPException(403); | ||
} else { | ||
(new RedirectResponse(Configuration::LOGIN_URL))->send(); | ||
} | ||
} | ||
} catch (\Throwable $exception) { | ||
//Clears partially rendered content | ||
ob_end_clean(); | ||
|
||
// if not HTTP exception wrap it to one | ||
if (!($exception instanceof HTTPException)) { | ||
$exception = HTTPException::from($exception); | ||
} | ||
// get handler instance | ||
$errorHandler = new (Configuration::ERROR_HANDLER_CLASS)(); | ||
// handle error and send response | ||
$errorHandler->handleError($this, $exception)->send(); | ||
} | ||
|
||
// if SQL debugging in configuration is allowed, display all SQL queries | ||
if (Configuration::SHOW_SQL_QUERY) { | ||
$queries = array_map(function ($q) { | ||
$lines = explode("\n", $q); | ||
$query = "Sent "; | ||
foreach ($lines as $line) { | ||
if (preg_match("/^Sent SQL: \[\d+\]/", $line)) { | ||
$query = $line; | ||
} else if (preg_match("/^Params: \d+/", $line)) { | ||
break; | ||
} else { | ||
$query .= $line . "\n"; | ||
} | ||
} | ||
return '<pre>' . trim($query) . '</pre>'; | ||
}, Connection::getQueryLog()); | ||
echo implode(PHP_EOL . PHP_EOL, $queries); | ||
} | ||
} | ||
|
||
/** | ||
* @return Router | ||
*/ | ||
public function getRouter(): Router | ||
{ | ||
return $this->router; | ||
} | ||
|
||
/** | ||
* @return Request | ||
*/ | ||
public function getRequest(): Request | ||
{ | ||
return $this->request; | ||
} | ||
|
||
/** | ||
* @return IAuthenticator|null | ||
*/ | ||
public function getAuth(): ?IAuthenticator | ||
{ | ||
return $this->auth; | ||
} | ||
|
||
/** | ||
* @return LinkGenerator | ||
*/ | ||
public function getLinkGenerator(): LinkGenerator | ||
{ | ||
return $this->linkGenerator; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
|
||
namespace App\Auth; | ||
|
||
use App\Core\IAuthenticator; | ||
|
||
/** | ||
* Class DummyAuthenticator | ||
* Basic implementation of user authentication | ||
* @package App\Auth | ||
*/ | ||
class DummyAuthenticator implements IAuthenticator | ||
{ | ||
public const LOGIN = "admin"; | ||
public const PASSWORD_HASH = '$2y$10$GRA8D27bvZZw8b85CAwRee9NH5nj4CQA6PDFMc90pN9Wi4VAWq3yq'; // admin | ||
public const USERNAME = "Admin"; | ||
|
||
/** | ||
* DummyAuthenticator constructor | ||
*/ | ||
public function __construct() | ||
{ | ||
session_start(); | ||
} | ||
|
||
/** | ||
* Verify, if the user is in DB and has his password is correct | ||
* @param $login | ||
* @param $password | ||
* @return bool | ||
* @throws \Exception | ||
*/ | ||
public function login($login, $password): bool | ||
{ | ||
if ($login == self::LOGIN && password_verify($password, self::PASSWORD_HASH)) { | ||
$_SESSION['user'] = self::USERNAME; | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* Logout the user | ||
*/ | ||
public function logout(): void | ||
{ | ||
if (isset($_SESSION["user"])) { | ||
unset($_SESSION["user"]); | ||
session_destroy(); | ||
} | ||
} | ||
|
||
/** | ||
* Get the name of the logged-in user | ||
* @return string | ||
* @throws \Exception | ||
*/ | ||
public function getLoggedUserName(): string | ||
{ | ||
return isset($_SESSION['user']) ? $_SESSION['user'] : throw new \Exception("User not logged in"); | ||
} | ||
|
||
/** | ||
* Get the context of the logged-in user | ||
* @return string | ||
*/ | ||
public function getLoggedUserContext(): mixed | ||
{ | ||
return null; | ||
} | ||
|
||
/** | ||
* Return if the user is authenticated or not | ||
* @return bool | ||
*/ | ||
public function isLogged(): bool | ||
{ | ||
return isset($_SESSION['user']) && $_SESSION['user'] != null; | ||
} | ||
|
||
/** | ||
* Return the id of the logged-in user | ||
* @return mixed | ||
*/ | ||
public function getLoggedUserId(): mixed | ||
{ | ||
return $_SESSION['user']; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php | ||
|
||
namespace App\Config; | ||
|
||
use App\Auth\DummyAuthenticator; | ||
use App\Core\ErrorHandler; | ||
|
||
/** | ||
* Class Configuration | ||
* Main configuration for the application | ||
* @package App\Config | ||
*/ | ||
class Configuration | ||
{ | ||
/** | ||
* App name | ||
*/ | ||
public const APP_NAME = 'Vaííčko MVC FW'; | ||
public const FW_VERSION = '2.2'; | ||
|
||
/** | ||
* DB settings | ||
*/ | ||
public const DB_HOST = 'db'; // see docker/docker-compose.yml | ||
public const DB_NAME = 'vaiicko_db'; // see docker/.env | ||
public const DB_USER = 'vaiicko_user'; // see docker/.env | ||
public const DB_PASS = 'dtb456'; // see docker/.env | ||
|
||
/** | ||
* URL where main page logging is. If action needs login, user will be redirected to this url | ||
*/ | ||
public const LOGIN_URL = '?c=auth&a=login'; | ||
/** | ||
* Prefix of default view in App/Views dir. <ROOT_LAYOUT>.layout.view.php | ||
*/ | ||
public const ROOT_LAYOUT = 'root'; | ||
/** | ||
* Add all SQL queries after app output | ||
*/ | ||
public const SHOW_SQL_QUERY = false; | ||
|
||
/** | ||
* Show detailed stacktrace using default exception handler. Should be used only for development. | ||
*/ | ||
public const SHOW_EXCEPTION_DETAILS = true; | ||
/** | ||
* Class used as authenticator. Must implement IAuthenticator | ||
*/ | ||
public const AUTH_CLASS = DummyAuthenticator::class; | ||
/** | ||
* Class used as error handler. Must implement IHandleError | ||
*/ | ||
public const ERROR_HANDLER_CLASS = ErrorHandler::class; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
namespace App\Controllers; | ||
|
||
use App\Core\AControllerBase; | ||
use App\Core\Responses\Response; | ||
|
||
/** | ||
* Class HomeController | ||
* Example class of a controller | ||
* @package App\Controllers | ||
*/ | ||
class AdminController extends AControllerBase | ||
{ | ||
/** | ||
* Authorize controller actions | ||
* @param $action | ||
* @return bool | ||
*/ | ||
public function authorize($action) | ||
{ | ||
return $this->app->getAuth()->isLogged(); | ||
} | ||
|
||
/** | ||
* Example of an action (authorization needed) | ||
* @return \App\Core\Responses\Response|\App\Core\Responses\ViewResponse | ||
*/ | ||
public function index(): Response | ||
{ | ||
return $this->html(); | ||
} | ||
} |
Oops, something went wrong.