Mise en place du tableau de bord Admin - Etape 1

This commit is contained in:
nox 2019-12-02 22:49:12 +01:00
parent e557174e96
commit 2f38ff0776
23 changed files with 340 additions and 155 deletions

6
.gitignore vendored
View File

@ -1,8 +1,8 @@
config/config.php
.idea
/public/uploads
/tmp
public/uploads
tmp
vendor
composer.json
composer.lock
/src/Framework/SwiftMailerFactory.php
src/Framework/SwiftMailerFactory.php

55
config/config-backup.php Normal file
View File

@ -0,0 +1,55 @@
<?php
use App\Framework\Twig\UrlExtension;
use Framework\Middleware\CsrfMiddleware;
use Framework\Renderer\RendererInterface;
use Framework\Renderer\TwigRendererFactory;
use Framework\Router;
use Framework\Router\RouterFactory;
use Framework\Router\RouterTwigExtension;
use Framework\Session\PHPSession;
use Framework\Session\SessionInterface;
use Framework\Twig\{
CsrfExtension, FlashExtension, FormExtension, PagerFantaExtension, TextExtension, TimeExtension
};
include 'conf.php';
return [
'env' => \DI\env('ENV', 'production'),
/*'env' => \DI\env('ENV', 'development'),*/
'database.host' => $host,
//'database.username' => 'guser',
'database.username' => $username,
//'database.password' => 'kptgT81U7nzYWHBdQ9',
'database.password' => $password,
'database.name' => $database_name,
'views.path' => dirname(__DIR__) . '/views',
'twig.extensions' => [
\DI\get(RouterTwigExtension::class),
\DI\get(PagerFantaExtension::class),
\DI\get(TextExtension::class),
\DI\get(TimeExtension::class),
\DI\get(FlashExtension::class),
\DI\get(FormExtension::class),
\DI\get(CsrfExtension::class),
\DI\get(UrlExtension::class)
],
SessionInterface::class => \DI\object(PHPSession::class),
CsrfMiddleware::class => \DI\object()->constructor(\DI\get(SessionInterface::class)),
Router::class => \DI\factory(RouterFactory::class),
RendererInterface::class => \DI\factory(TwigRendererFactory::class),
\PDO::class => function (\Psr\Container\ContainerInterface $c) {
return new PDO(
'mysql:host='. $c->get('database.host') . ';dbname=' . $c->get('database.name'),
$c->get('database.username'),
$c->get('database.password'),
[
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]
);
},
// MAILER
'mail.to' => 'mailto@admin.fr',
'mail.from' => 'no-reply@admin.fr',
Swift_Mailer::class => \DI\factory(\Framework\SwiftMailerFactory::class)
];

View File

@ -34,18 +34,14 @@ $app = (new \Framework\App( $chemin_new .'config/apply.php'))
$container = $app->getContainer();
// Pose un problème
//$container->get(\Framework\Router::class)->get('/', \App\Gmarche\Actions\RegionIndexAction::class, 'home');
$app->pipe(Whoops::class);
$app->pipe(TrailingSlashMiddleware::class);
$app->pipe(\App\Auth\ForbiddenMiddleware::class);
// admin pose problème
//$app->pipe(
// $container->get('admin.prefix'),
// $container->get(RoleMiddlewareFactory::class)->makeForRole('admin')
// );
$app->pipe(
$container->get('admin.prefix'),
$container->get(RoleMiddlewareFactory::class)->makeForRole('0','1')
);
$app->pipe(MethodMiddleware::class)
->pipe(RendererRequestMiddleware::class)

View File

@ -8,7 +8,7 @@ try {
if (isset($_POST['nom_connecte']) && isset($_POST['mdp']) != "") {
$params["username"] = $_POST['nom_connecte'];
$requete = "SELECT username, password
$requete = "SELECT username, password, role
FROM users
WHERE username = :username";
$query = $bdd->prepare($requete);
@ -17,6 +17,7 @@ try {
if (password_verify($_POST['mdp'],$row['password'])) {
session_start();
$_SESSION['user']=$row['username'];
$_SESSION['role']=$row['role'];
echo '{"valide":true,"username":"'.$row['username'].'"}';
} else {
echo '{"valide":false}';

View File

@ -28,7 +28,9 @@ class ProfilAction
public function __invoke(ServerRequestInterface $request)
{
/* Transmission du nom de l'utilistateur connecté à la vue Twig */
session_start();
if (!isset($_SESSION)) {
session_start();
}
if (isset($_SESSION['user'])) {
$nom_user = $_SESSION['user'];
} else {

View File

@ -2,8 +2,8 @@
namespace App\Admin;
use App\Product\Actions\ProductIndexAction;
use App\Product\Actions\ProductCrudAction;
use App\Admin\Table\UserTable;
use Framework\Auth;
use Framework\Module;
use Framework\Renderer\RendererInterface;
use Framework\Renderer\TwigRenderer;
@ -13,19 +13,41 @@ class AdminModule extends Module
{
const DEFINITIONS = __DIR__ . '/config.php';
/**
* @var Auth
*/
private $auth;
public function __construct(
RendererInterface $renderer,
Router $router,
AdminTwigExtension $adminTwigExtension,
UserTable $userTable,
Auth $auth,
string $prefix
) {
)
{
$this->userTable = $userTable;
$this->auth = $auth;
$renderer->addPath('admin', __DIR__ . '/views');
$name_user = $this->auth->getUser()->username;
//$role = $user->getRoles();
$role = $_SESSION['role'];
$page = $params['p'] ?? 1; // Si la page n'est pas définie, on l'initialise à 1
//$liste_users = $this->userTable->findAll()->paginate(25, $page);
$liste_adminGeneral = $this->userTable->findAdminUsers('1');
$liste_adminAntenne = $this->userTable->findAdminUsers('2');
$liste_users = $this->userTable->findAdminUsers('3');
//$router->get('/machin', ProductCrudAction::class, 'machin.bidule'); // ProductIndexAction
/*if ($renderer instanceof TwigRenderer) {
$router->get($prefix, DashboardAction::class, 'admin');
$router->post($prefix, DashboardAction::class);
if ($renderer instanceof TwigRenderer) {
$renderer->getTwig()->addExtension($adminTwigExtension);
}*/
$renderer->getTwig()->addGlobal('role',$role);
$renderer->getTwig()->addGlobal('name_user',$name_user);
$renderer->getTwig()->addGlobal('liste_adminGeneral',$liste_adminGeneral);
$renderer->getTwig()->addGlobal('liste_adminAntenne',$liste_adminAntenne);
$renderer->getTwig()->addGlobal('liste_users',$liste_users);
}
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Admin;
use Framework\Renderer\RendererInterface;
class DashboardAction
{
/**
* @var RendererInterface
*/
private $renderer;
//private $widgets;
public function __construct(RendererInterface $renderer)
{
$this->renderer = $renderer;
// $this->widgets = $widgets;
}
public function __invoke()
{
if ($request->getMethod() === 'GET') {
/*$widgets = array_reduce($this->widgets, function (string $html, AdminWidgetInterface $widget) {
return $html . $widget->render();
}, '');*/
return $this->renderer->render('@admin/dashboard');
}
}
}

32
src/Admin/Entity/User.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace App\Admin\Entity;
class User
{
public $id;
public $username;
public $email;
public $password;
public $firstname;
public $lastname;
public $created_at;
public $role;
public $password_reset;
public $password_reset_at;
public $pubkey;
public $avatar;
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Admin\Table;
use App\Admin\Entity\User;
use Framework\Database\Query;
use Framework\Database\Table;
class UserTable extends Table
{
protected $entity = User::class;
protected $table = 'users';
public function findAdminUsers($role): Query
{
//$region = new RegionTable($this->pdo);
return $this->makeQuery()
->select('u.*')
->where("u.role = $role")
->order('u.username ASC');
}
public function findRole($username): Query
{
//$region = new RegionTable($this->pdo);
return $this->makeQuery()
->select('u.role')
->where("u.username = $username");
}
}

View File

@ -0,0 +1,59 @@
{% extends '@admin/layout.twig' %}
{% block body %}
<h3 style="display:inline-block;">Tableau de bord - </h3>
<h4 style="display:inline-block;">
{% if role == '0' %} Super Admin{% endif %}
{% if role == '1' %} Admin général{% endif %}
{% if role == '2' %} Admin Antenne{% endif %}
</h4>
</h3>
<p></p>
{% if role == '0' %}
<h4>Liste des admins généraux</h4>
<ul class="list-group list-group-flush">
{% for admin_gen in liste_adminGeneral %}
<a style="color:black;" href="" title="{{ admin_gen.username }}">
<li class="liste_antennes list-group-item" style="padding: .2rem 1.25rem;">
{{ admin_gen.username }}
</li>
</a>
{% endfor %}
</ul>
{% endif %}
{% if (role == '0' or role == '1') %}
<h4>Liste des admins Antenne</h4>
<ul class="list-group list-group-flush">
{% for admin_ant in liste_adminAntenne %}
<a style="color:black;" href="" title="{{ admin_ant.username }}">
<li class="liste_antennes list-group-item" style="padding: .2rem 1.25rem;">
{{ admin_ant.username }}
</li>
</a>
{% endfor %}
</ul>
{% endif %}
{% if (role == '0' or role == '1' or role == '2') %}
<h4>Liste des utilisateurs</h4>
<ul class="list-group list-group-flush">
{% for user in liste_users %}
<a style="color:black;" href="" title="{{ user.username }}">
<li class="liste_antennes list-group-item" style="padding: .2rem 1.25rem;">
{{ user.username }}
</li>
</a>
{% endfor %}
</ul>
{% endif %}
<p></p>
{% if (role == '0' or role == '1') %}
<h4>Gestion d'une antenne</h4>
{% endif %}
<p></p>
{% if (role == '0' or role == '1' or role == '2') %}
<h4>Gestion d'un G-Marché</h4>
{% endif %}
<div class="row">
{{ widgets | raw }}
</div>
{% endblock %}

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>{% block title "Mon site " %}</title>
<title>{% block title "Ğ1-Marché - Administration" %}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/3.0.7/flatpickr.css">
<style>
@ -13,17 +13,42 @@
<body>
<nav class="navbar fixed-top navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="{{ path(routePrefix) }}">Ğ1-Marché</a>
<a class="navbar-brand" href="{{ path('gmarche.index') }}">Ğ1-Marché</a>
<ul class="navbar-nav mr-auto">
{{ admin_menu() }}
</ul>
<div class="navbar-nav">
<form class="nav-item active" method="post" action="{{ path('auth.logout') }}">
{{ csrf_input() }}
<button class="btn-primary btn-danger">Se déconnecter</button>
</form>
</div>
<ul class="navbar-nav mr-auto" style="color: white;">
<!-- admin_menu() -->
role = {{ role }}
</ul>
<div class="navbar-nav">
<div class="navbar-text" style="color:lightgray;margin-right:15px; margin-top:3px;">
{{ "now"|date('d/m/y') }}
</div>
{% if name_user != '' %}
<form method="post" style="margin-top:5px;" action="{{ path('account.profil') }}">
<span><img src="\avatar_user.png" width="22" height="22" /></span>
<button style="color:white;font-size: 14px;" class="btn-primary">{{ name_user }}</button>
</form>
<form method="post" action="{{ path('auth.logout') }}">
<!-- csrf_input() }}-->
<button class="btn btn-danger" style="margin-left: 7px; font-size:14px;">Se déconnecter</button>
</form>
{% else %}
<div class="nav-item" id="bouton-connexion">
<button style="color:white; font-size: 14px;" class="btn btn-primary" data-toggle="modal" data-target="#connexion_modal">Se connecter</button>
</div>
<div id="nom_connecte" style="display:none;margin-left:10px;margin-top:6px;margin-right:8px;">
</div>
<div id="deconnexion" style="display:none;">
<form method="post" action="{{ path('auth.logout') }}">
<!-- csrf_input() }}-->
<button class="btn btn-danger" style="font-size:14px;">Se déconnecter</button>
</form>
</div>
<div class="nav-item" id="inscription">
<a class="nav-link" href="{{ path('account.signup') }}" style="font-size:14px;">S'inscrire</a>
</div>
{% endif %}
</div>
</nav>
<div class="container">
@ -47,14 +72,6 @@
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/3.0.7/flatpickr.js"></script>
<script>
flatpickr('.datepicker', {
enableTime: true,
altInput: true,
altFormat: 'j F Y, H:i',
dateFormat: 'Y-m-d H:i:S'
})
</script>
</body>
</html>

View File

@ -1,6 +1,7 @@
<?php
namespace App\Auth\Action;
use App\Admin\Table\UserTable;
use App\Auth\DatabaseAuth;
use Framework\Actions\RouterAwareAction;
use Framework\Renderer\RendererInterface;
@ -37,12 +38,14 @@ class LoginAttemptAction
RendererInterface $renderer,
DatabaseAuth $auth,
Router $router,
SessionInterface $session
SessionInterface $session,
UserTable $userTable
) {
$this->renderer = $renderer;
$this->auth = $auth;
$this->router = $router;
$this->session = $session;
$this->userTable = $userTable;
}
public function __invoke(ServerRequestInterface $request)
@ -53,7 +56,10 @@ class LoginAttemptAction
if(!isset($_SESSION)) {
session_start();
}
$nom_user = $_SESSION['user'] = $params['username'];
$_SESSION['role'] = $this->userTable->findRole($params['username']);
//$nom_user = $_SESSION['user'] = $params['username'];
$_SESSION['user'] = $params['username'];
//$path = $this->router->generateUri('admin');
$path = $this->session->get('auth.redirect') ?? $this->router->generateUri('gmarche.index');
$this->session->delete('auth.redirect');
return new RedirectResponse($path);

View File

@ -42,7 +42,9 @@ class LogoutAction
public function __invoke(ServerRequestInterface $request)
{
$gmarchePrefix = $this->container->get('gmarche.prefix');
session_start();
if(!isset($_SESSION)) {
session_start();
}
unset($_SESSION['user']);
$this->auth->logout();
$this->flashService->success('Vous êtes maintenant déconnecté');

View File

@ -26,7 +26,9 @@ class ContactAction
public function __invoke(ServerRequestInterface $request)
{
if ($request->getMethod() === 'GET') {
session_start();
if (!isset($_SESSION)) {
session_start();
}
if (isset($_SESSION['user'])) {
$nom_user = $_SESSION['user'];
} else {

View File

@ -19,16 +19,26 @@ class RoleMiddleware implements MiddlewareInterface
*/
private $role;
public function __construct(Auth $auth, string $role)
public function __construct(Auth $auth, string $role, string $role2)
{
$this->auth = $auth;
$this->role = $role;
$this->role2 = $role2;
}
public function process(ServerRequestInterface $request, DelegateInterface $delegate): ResponseInterface
{
$user = $this->auth->getUser();
if ($user === null || !in_array($this->role, $user->getRoles())) {
//if (array_key_exists('premier', $search_array))
$non_admin = true;
if (!in_array($this->role, [$_SESSION['role']])) {
$non_admin = false;
}
if (!in_array($this->role2, [$_SESSION['role']])) {
$non_admin = false;
}
if ($user === null || $non_admin ) {
//if ($user === null || !array_key_exists($chaine_user,$this->role)) {
throw new ForbiddenException();
}
return $delegate->process($request);

View File

@ -17,8 +17,8 @@ class RoleMiddlewareFactory
$this->auth = $auth;
}
public function makeForRole($role): RoleMiddleware
public function makeForRole($role, $role2): RoleMiddleware
{
return new RoleMiddleware($this->auth, $role);
return new RoleMiddleware($this->auth, $role, $role2);
}
}

View File

@ -9,7 +9,8 @@ class SwiftMailerFactory
public function __invoke(ContainerInterface $container): \Swift_Mailer
{
if ($container->get('env') === 'production') {
$transport = new \Swift_SendmailTransport();
$transport = new \Swift_SmtpTransport('localhost', 1025);
//$transport = new \Swift_SendmailTransport();
} else {
$transport = new \Swift_SmtpTransport('localhost', 1025);
}

View File

@ -1,98 +0,0 @@
<?php
namespace App\Framework\Twig;
use App\Gmarche\Table\AntenneTable;
use App\Gmarche\Table\RegionTable;
use App\Product\Table\ProductTable;
use Framework\Actions\RouterAwareAction;
use Framework\Database\Table;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
class AntenneExtension extends \Twig_Extension
{
/**
* @var table
*/
private $table;
private $productTable;
private $regionTable;
private $antenneTable;
private $container;
// use RouterAwareAction;
// private $antenne_slug;
public function __construct(AntenneTable $antenneTable = null)
{
// $this->antenne_slug = $antenne_slug;
$this->table = $table;
$this->productTable = $productTable;
$this->regionTable = $regionTable;
$this->antenneTable = $antenneTable;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('current_antenne', [$this, 'currentAntenne'])
];
}
/* public function pathFor(string $path, array $params = []): string
{
return $this->router->generateUri($path, $params);
}*/
/**
* @return \PDO
*/
public function getPdo(): \PDO
{
return $this->pdo;
}
public function currentAntenne(?\PDO $pdo = null, string $antenne_slug): int
{
//echo "antenne_slug=".$antenne_slug;
// die();
//$params = $request->getQueryParams();
echo "pdo";
var_dump($pdo);
die();
if (self::getPdo()) {
echo 'PDO true';
die();
} else {
echo 'PDO false';
die();
}
$region_id = $this->antenneTable->findBy('slug', 'paris')->id;
echo 'region_id';
var_dump($region_id);
// $test = $this->antenneTable->findWithAntenne('paris');
//$test2 = $this->table->findAllbyRegion(8);
$test1 = $this->productTable;
echo 'test1';
var_dump($test1);
$test2 = $this->table;
echo 'test2';
var_dump($test2);
die();
$test = $this->productTable->findBy('slug', 'badge');
echo 'test = ';
var_dump($test);
die();
echo 'test2 = '.var_dump($test2);
die();
//return $this->antenneTable->findBy('slug', 'paris')->id;
// return(1);
}
}

View File

@ -60,7 +60,9 @@ class AntenneShowAction
'id' => $region->id
]);
}*/
session_start();
if (!isset($_SESSION)) {
session_start();
}
if (isset($_SESSION['user'])) {
$nom_user = $_SESSION['user'];
} else {

View File

@ -20,12 +20,17 @@ class RegionIndexAction
}
public function __invoke()
{
session_start();
if (!isset($_SESSION)) {
session_start();
}
$accueil = true;
if (isset($_SESSION['user'])) {
$nom_user = $_SESSION['user'];
$role = $_SESSION['role'];
} else {
$nom_user = '';
$role = '3';
}
return $this->renderer->render('@gmarche/index', compact('nom_user'));
return $this->renderer->render('@gmarche/index', compact('nom_user','accueil','role'));
}
}

View File

@ -56,7 +56,9 @@ class ProductIndexAction
$page = $params['p'] ?? 1;
$viewPath = '@product/admin/products';
$items = $this->productTable->findByAntenneId('antenne_id', $antenne_id)->paginate(20, $page);
session_start();
if (!isset($_SESSION)) {
session_start();
}
if (isset($_SESSION['user'])) {
$nom_user = $_SESSION['user'];
$requete_user = $this->userTable->findBy('username', $nom_user);

View File

@ -58,7 +58,9 @@ class RechIndexAction
//$routePrefix = 'product.index';
$viewPath = '@product/admin/recherches';
$items = $this->rechTable->findByAntenneId('antenne_id', $antenne_id)->paginate(20, $page);
session_start();
if (!isset($_SESSION)) {
session_start();
}
if (isset($_SESSION['user'])) {
$nom_user = $_SESSION['user'];
$requete_user = $this->userTable->findBy('username', $nom_user);

View File

@ -41,9 +41,15 @@
<a class="navbar-brand" href="#">Ğ1-Marché</a>
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link {% if regions %} active{% endif %}" style="font-size:14px;"
<a class="nav-link {% if accueil %} active{% endif %}" style="font-size:14px;"
href="{{ path('gmarche.index') }}">Accueil</a>
</li>
{% if role=='0' or role=='1' or role=='2' %}
<li class="nav-item">
<a class="nav-link {% if admin %} active{% endif %}" style="font-size:14px;"
href="{{ path('admin') }}">Administration</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link {% if explodeUrl()[1]=='contact' %} active{% endif %}" style="font-size:14px;"
href="{{ path('contact') }}">Qui sommes-nous ?</a>
@ -54,10 +60,8 @@
{{ "now"|date('d/m/y') }}
</div>
{% if nom_user != '' %}
<!-- <button style="background-color: transparent;padding:0;border:0;" -->
<form method="post" style="margin-top:5px;" action="{{ path('account.profil') }}">
<span><img src="\avatar_user.png" width="22" height="22" /></span>
<!--<span id="nom_connecte"> nom_user </span>-->
<button style="color:white;font-size: 14px;" class="btn-primary">{{ nom_user }}</button>
</form>
<form method="post" action="{{ path('auth.logout') }}">