Compare commits
No commits in common. "5e8c945170086e32cb9e8d4ffb29933909299890" and "61aa012dd63fefaaa427df380fcdf48d13826f45" have entirely different histories.
5e8c945170
...
61aa012dd6
|
@ -16,7 +16,6 @@ class User
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private string $nick = '',
|
private string $nick = '',
|
||||||
private string $password = '',
|
private string $password = '',
|
||||||
private readonly string $newPassword = '',
|
|
||||||
private string $first = '',
|
private string $first = '',
|
||||||
private string $last = '',
|
private string $last = '',
|
||||||
private int $id = 0,
|
private int $id = 0,
|
||||||
|
@ -24,21 +23,7 @@ class User
|
||||||
private UserAuth $userAuth = UserAuth::AUTH_ANONYMOUS
|
private UserAuth $userAuth = UserAuth::AUTH_ANONYMOUS
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!empty($this->newPassword)) {
|
// empty body
|
||||||
echo "password";
|
|
||||||
$this->password = password_hash(password: $this->newPassword, algo: PASSWORD_ARGON2I);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
|
||||||
// ANONYMOUS has id 0
|
|
||||||
if ($this->id != 0) {
|
|
||||||
if ($this->isAdmin) {
|
|
||||||
$this->userAuth = UserAuth::AUTH_ADMIN;
|
|
||||||
} else {
|
|
||||||
$this->userAuth = UserAuth::AUTH_USER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNick(): string
|
public function getNick(): string
|
||||||
|
@ -101,12 +86,12 @@ class User
|
||||||
$this->isAdmin = $isAdmin;
|
$this->isAdmin = $isAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAuth(): UserAuth
|
public function getAuth()
|
||||||
{
|
{
|
||||||
return $this->userAuth;
|
return UserAuth::AUTH_ANONYMOUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setAuth(UserAuth $userAuth): void
|
public function setAuth(UserAuth $userAuth)
|
||||||
{
|
{
|
||||||
$this->userAuth = $userAuth;
|
$this->userAuth = $userAuth;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,62 +1,29 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
|
||||||
* Copyright (c) 2022. Micha Espey <tracer@24unix.net>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use App\Controller\AddressBookAdminController;
|
use App\Controller\AddressBook;
|
||||||
use App\Controller\AddressBookController;
|
|
||||||
use App\Controller\SecurityController;
|
|
||||||
use App\Entity\User;
|
|
||||||
use App\Repository\UserRepository;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A quick and dirty class container for DI.
|
|
||||||
* Caveat: Classes are always instantiated
|
|
||||||
* No autowiring (yet, maybe later, but it might fit for a demo)
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Container
|
class Container
|
||||||
{
|
{
|
||||||
|
// caveat: Classes are always instantiated
|
||||||
|
// No autowiring (yet, maybe later, but it might fit for a demo)
|
||||||
|
|
||||||
private AddressBookController $addressBook;
|
|
||||||
private AddressBookAdminController $addressBookAdmin;
|
|
||||||
private Config $config;
|
|
||||||
private DatabaseConnection $databaseConnection;
|
|
||||||
private Router $router;
|
|
||||||
private SecurityController $securityController;
|
|
||||||
private Template $template;
|
private Template $template;
|
||||||
private User $user;
|
private AddressBook $addressBook;
|
||||||
private UserRepository $userRepository;
|
private Router $router;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->config = new Config();
|
|
||||||
$this->databaseConnection = new DatabaseConnection(config: $this->config);
|
|
||||||
$this->template = new Template(templateDir: dirname(path: __DIR__, levels: 2) . '/templates/');
|
$this->template = new Template(templateDir: dirname(path: __DIR__, levels: 2) . '/templates/');
|
||||||
$this->router = new Router(template: $this->template);
|
$this->addressBook = new AddressBook(template: $this->template);
|
||||||
$this->userRepository = new UserRepository(databaseConnection: $this->databaseConnection);
|
$this->router = new Router();
|
||||||
$this->securityController = new SecurityController(template: $this->template, userRepository: $this->userRepository, router: $this->router);
|
|
||||||
if (empty($_SESSION['user_id'])) {
|
|
||||||
$this->user = new User(); // ANONYMOUS
|
|
||||||
} else {
|
|
||||||
$this->user = $this->userRepository->findByID(id: $_SESSION['user_id']);
|
|
||||||
}
|
|
||||||
$this->addressBook = new AddressBookController(template: $this->template, user: $this->user, userRepository: $this->userRepository, router: $this->router);
|
|
||||||
$this->addressBookAdmin = new AddressBookAdminController(template: $this->template, user: $this->user, userRepository: $this->userRepository, router: $this->router);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $className): object
|
public function get(string $className): object
|
||||||
{
|
{
|
||||||
return match ($className) {
|
return match ($className) {
|
||||||
'App\Controller\AddressBookController' => $this->addressBook,
|
'App\Controller\AddressBook' => $this->addressBook,
|
||||||
'App\Controller\AddressBookAdminController' => $this->addressBookAdmin,
|
|
||||||
'App\Controller\SecurityController' => $this->securityController,
|
|
||||||
'App\Service\Router' => $this->router,
|
'App\Service\Router' => $this->router,
|
||||||
//default => throw new Exception(message: "Missing class definition: $class")
|
//default => throw new Exception(message: "Missing class definition: $class")
|
||||||
default => die("Missing class definition: $className")
|
default => die("Missing class definition: $className")
|
||||||
|
|
|
@ -16,17 +16,17 @@ use Closure;
|
||||||
/*
|
/*
|
||||||
* A small router implementation for the address book demo.
|
* A small router implementation for the address book demo.
|
||||||
* Currently it doesn't handle GET requests, as not needed.
|
* Currently it doesn't handle GET requests, as not needed.
|
||||||
* But if I reuse the code in my bindApi I'll maybe support GET as well.
|
* But if I reuse the code in my bindApi I'll support GET as well.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Router
|
class Router
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The easiest way to differentiate between static and dynamic routes is using
|
* The easiest wy to differentiate between static and dynamic routes is using
|
||||||
* two arrays, no need to pollute the class Route with that information
|
* two arrays, no need to pollute the class Route with that information
|
||||||
*/
|
*/
|
||||||
private array $staticRoutes = [];
|
private array $staticRoutes;
|
||||||
private array $dynamicRoutes = [];
|
private array $dynamicRoutes;
|
||||||
|
|
||||||
public function __construct(private readonly Template $template)
|
public function __construct(private readonly Template $template)
|
||||||
{
|
{
|
||||||
|
@ -44,9 +44,13 @@ class Router
|
||||||
$parameters = $matches[0];
|
$parameters = $matches[0];
|
||||||
|
|
||||||
// create regex for route:
|
// create regex for route:
|
||||||
$regex = preg_replace(pattern: '/{.+?}/', replacement: '([a-zA-Z0-9]*)', subject: $route);
|
$regex = preg_replace(pattern: '/(?<={).+?(?=})/', replacement: '(.*?)', subject: $route);
|
||||||
$regex = '/^' . str_replace(search: "/", replace: '\\/', subject: $regex) . '$/i';
|
|
||||||
|
|
||||||
|
// code below is ugly, better match including the braces
|
||||||
|
$regex = str_replace(search: '{', replace: '', subject: $regex);
|
||||||
|
$regex = str_replace(search: '}', replace: '', subject: $regex);
|
||||||
|
|
||||||
|
$regex = '/^' . str_replace(search: "/", replace: '\\/', subject: $regex) . '$/i';
|
||||||
$route = new Route(name: $name, route: $route, regEx: $regex, parameters: $parameters, callback: $callback);
|
$route = new Route(name: $name, route: $route, regEx: $regex, parameters: $parameters, callback: $callback);
|
||||||
|
|
||||||
if ($parameters) {
|
if ($parameters) {
|
||||||
|
@ -57,7 +61,7 @@ class Router
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if there is a known route and executes the callback.
|
* Check if there is a known route and executes the callback.
|
||||||
*/
|
*/
|
||||||
public function handleRouting(): void
|
public function handleRouting(): void
|
||||||
{
|
{
|
||||||
|
@ -67,56 +71,28 @@ class Router
|
||||||
* Static routes have preference over dynamic ones, so
|
* Static routes have preference over dynamic ones, so
|
||||||
* /admin/user/add to add and
|
* /admin/user/add to add and
|
||||||
* /admin/user/{name} to edit is possible.
|
* /admin/user/{name} to edit is possible.
|
||||||
* A user named "add" of course not :)
|
|
||||||
*
|
|
||||||
* But who wants to call their users "add" or "delete"?
|
|
||||||
* That's as weird as Little Bobby Tables … (https://xkcd.com/327/)
|
|
||||||
*/
|
*/
|
||||||
foreach ($this->staticRoutes as $route) {
|
foreach ($this->staticRoutes as $route) {
|
||||||
if (preg_match(pattern: $route->getRegex(), subject: $requestUri, matches: $matches)) {
|
if (preg_match(pattern: $route->getRegex(), subject: $requestUri, matches: $matches)) {
|
||||||
call_user_func(callback: $route->getCallback());
|
call_user_func(callback: $route->getCallback());
|
||||||
|
|
||||||
// We've found our route, bail out.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->dynamicRoutes as $route) {
|
foreach ($this->dynamicRoutes as $route) {
|
||||||
$parameters = [];
|
|
||||||
if (preg_match(pattern: $route->getRegex(), subject: $requestUri, matches: $matches)) {
|
if (preg_match(pattern: $route->getRegex(), subject: $requestUri, matches: $matches)) {
|
||||||
|
$parameters = [];
|
||||||
foreach ($route->getParameters() as $id => $parameter) {
|
foreach ($route->getParameters() as $id => $parameter) {
|
||||||
$parameters[$parameter] = $matches[$id + 1];
|
$parameters[$parameter] = $matches[$id + 1];
|
||||||
}
|
}
|
||||||
// PHP is mad about named parameters in call_user_func when adding parameters.
|
// PHP is mad about named parameters in call_user_func
|
||||||
// Uncaught Error: Unknown named parameter $args in <sourceFile>
|
// Uncaught Error: Unknown named parameter $args in …
|
||||||
// But PHPStorm seems happy without them. So what?
|
// But PHPStorm seems happy without them. So what?
|
||||||
call_user_func($route->getCallback(), $parameters);
|
call_user_func($route->getCallback(), $parameters);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if no route is matched, throw a 404
|
|
||||||
$this->template->render(templateName: 'status/404.html.php');
|
$this->template->render(templateName: 'status/404.html.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function path(string $routeName, array $vars = [])
|
|
||||||
{
|
|
||||||
foreach (array_merge($this->dynamicRoutes, $this->staticRoutes) as $route) {
|
|
||||||
|
|
||||||
if ($route->getName() == $routeName) {
|
|
||||||
if ($vars) {
|
|
||||||
// build route
|
|
||||||
$route = $route->getRoute();
|
|
||||||
// replace placeholder with current values
|
|
||||||
foreach ($vars as $key => $value) {
|
|
||||||
$route = str_replace(search: '{' . $key . '}', replace: $value, subject: $route);
|
|
||||||
}
|
|
||||||
return $route;
|
|
||||||
} else {
|
|
||||||
return $route->getRoute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// no 404, this is reached only if the code is wrong
|
|
||||||
die("Missing Route: $routeName");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<?php include dirname(path: __DIR__) . '/_header.html.php'; ?>
|
<?php include dirname(path: __DIR__) . '/_header.html.php'; ?>
|
||||||
|
|
||||||
<h1>Address Book - Admin</h1>
|
<h1>Address Book - Admin</h1>
|
||||||
<a href="<?= $router->path('app_admin_users') ?>">👱Users</a>
|
<a href="/admin/users">👱Users</a>
|
||||||
|
|
||||||
<?php include dirname(path: __DIR__) . '/_footer.html.php' ?>
|
<?php include dirname(path: __DIR__) . '/_footer.html.php' ?>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<th>First</th>
|
<th>First</th>
|
||||||
<th>Last</th>
|
<th>Last</th>
|
||||||
<th>Is Admin</th>
|
<th>Is Admin</th>
|
||||||
<th colspan="2"> </th>
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
<?php foreach ($users as $userLine): ?>
|
<?php foreach ($users as $userLine): ?>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -22,14 +22,11 @@
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="<?= $router->path('app_admin_users_edit', vars: ['nick' => $userLine->getNick()]); ?>">edit</a>
|
<a href="/admin/users/<?= $userLine->getNick(); ?>">edit</a>
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="<?= $router->path('app_admin_users_delete', vars: ['nick' => $userLine->getNick()]); ?>">delete</a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</table>
|
</table>
|
||||||
<a href="<?= $router->path('app_admin_users_add'); ?>">Add User</a>
|
<a href="/admin/users/add">Add User</a>
|
||||||
|
|
||||||
<?php include dirname(path: __DIR__) . '/_footer.html.php' ?>
|
<?php include dirname(path: __DIR__) . '/_footer.html.php' ?>
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
<input type="text" name="nick" id="nick" required>
|
<input type="text" name="nick" id="nick" required>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<label for="new_password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input type="password" name="new_password" id="new_password" required>
|
<input type="password" name="password" id="password" required>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<label for="first">First</label>
|
<label for="first">First</label>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<input type="text" name="last" id="last" required>
|
<input type="text" name="last" id="last" required>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<label for="is_admin">Is Admin</label>
|
<label for="is-admin">Is Admin</label>
|
||||||
<input type="checkbox" name="is_admin" id="is_admin">
|
<input type="checkbox" name="is_admin" id="is_admin">
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
<input type="text" name="nick" id="nick" value="<?= $editUser->getNick() ?>" required>
|
<input type="text" name="nick" id="nick" value="<?= $editUser->getNick() ?>" required>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<label for="new_password">Password (leave empty to keep the current one)</label>
|
<label for="password">Password (leave empty to keep the current one)</label>
|
||||||
<input type="password" name="new_password" id="new_password">
|
<input type="password" name="password" id="password">
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<label for="first">First</label>
|
<label for="first">First</label>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<input type="text" name="last" id="last" value="<?= $editUser->getLast() ?>" required>
|
<input type="text" name="last" id="last" value="<?= $editUser->getLast() ?>" required>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<label for="is_admin">Is Admin</label>
|
<label for="is-admin">Is Admin</label>
|
||||||
<input type="checkbox" name="is_admin" id="is_admin" <?= $editUser->isAdmin()?'checked':'' ?>>
|
<input type="checkbox" name="is_admin" id="is_admin" <?= $editUser->isAdmin()?'checked':'' ?>>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue