Compare commits

...

4 Commits

Author SHA1 Message Date
David D'ALMEIDA 9eb7074df5 push
continuous-integration/drone/push Build is failing Details
1 year ago
David D'ALMEIDA adb9584cba work with APE
continuous-integration/drone/push Build is failing Details
1 year ago
Antoine PINAGOT d0d1d4c23d auth Ctrl fini
continuous-integration/drone/push Build is failing Details
1 year ago
David D'ALMEIDA f804820e85 exemple
continuous-integration/drone/push Build is failing Details
1 year ago

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 2.0 MiB

@ -34,6 +34,9 @@
"altorouter/altorouter": "1.1.0", "altorouter/altorouter": "1.1.0",
"psr/container": "^2.0" "psr/container": "^2.0"
}, },
"config": {
"process-timeout": 2000
},
"require-dev": { "require-dev": {
"phpunit/phpunit": "*" "phpunit/phpunit": "*"
}, },

@ -11,7 +11,7 @@ $dotenv->safeLoad();
// const DB_DATABASE = $_ENV['DB_DATABASE'] ?? 'heartTrack'; // const DB_DATABASE = $_ENV['DB_DATABASE'] ?? 'heartTrack';
// const DB_USER = $_ENV['DB_USER'] ?? 'toto'; // const DB_USER = $_ENV['DB_USER'] ?? 'toto';
// const DB_PASSWORD = $_ENV['DB_PASSWORD'] ?? 'achanger'; // const DB_PASSWORD = $_ENV['DB_PASSWORD'] ?? 'achanger';
define("APP_ENV", 'development'); define("APP_ENV", getenv('APP_ENV'));
const DB_HOST = 'localhost'; const DB_HOST = 'localhost';
const DB_DATABASE = 'heartTrack'; const DB_DATABASE = 'heartTrack';

@ -12,7 +12,7 @@ use Manager\DataManager;
use Repository\IUserRepository; use Repository\IUserRepository;
use Shared\ArgumentControllerResolver; use Shared\ArgumentControllerResolver;
use Shared\IArgumentResolver; use Shared\IArgumentResolver;
use Stub\AuthService; use Network\AuthService;
use Stub\NotificationRepository; use Stub\NotificationRepository;
use Stub\TrainingRepository; use Stub\TrainingRepository;
use Stub\UserRepository; use Stub\UserRepository;
@ -30,13 +30,13 @@ use Network\RelationshipService;
use Network\INotificationService; use Network\INotificationService;
use Stub\NotificationService; use Stub\NotificationService;
use App\Router\Session;
use Stub\StubData; use Stub\StubData;
use Twig\Environment; use Twig\Environment;
use Twig\Loader\FilesystemLoader; use Twig\Loader\FilesystemLoader;
use Shared\IHashPassword; use Shared\IHashPassword;
use Shared\HashPassword; use Shared\HashPassword;
use Shared\Log;
$appFactory = new AppCreator(); $appFactory = new AppCreator();
$appFactory->registerService(IArgumentResolver::class, ArgumentControllerResolver::class); $appFactory->registerService(IArgumentResolver::class, ArgumentControllerResolver::class);
@ -54,7 +54,6 @@ $appFactory->registerService(IUserRepository::class, UserRepository::class);
$appFactory->registerService(\Twig\Loader\LoaderInterface::class, function() { $appFactory->registerService(\Twig\Loader\LoaderInterface::class, function() {
return new FilesystemLoader(__DIR__ . '/../src/app/views/Templates'); return new FilesystemLoader(__DIR__ . '/../src/app/views/Templates');
}); });
@ -69,7 +68,7 @@ $app = $appFactory->create();
if (!is_null($app)){ if (!is_null($app)){
// Ajout des Middleware // Ajout des Middleware
/*$app->use(new LoggingMiddleware());*/ /*$app->use(new LoggingMiddleware());*/
$app->use(new AuthMiddleware()); $app->use(new AuthMiddleware($appFactory->getDicontainer()->get(IAuthService::class) ));
$app->mapControllers(); $app->mapControllers();
$app->run(RequestFactory::createFromGlobals()); $app->run(RequestFactory::createFromGlobals());
} }

@ -29,9 +29,6 @@ class App
private FrontController $frontController; private FrontController $frontController;
private Session $session;
public function __construct(string $appName, int $version, \App\Container $diContainer) public function __construct(string $appName, int $version, \App\Container $diContainer)
{ {
$this->appName = $appName; $this->appName = $appName;
@ -39,7 +36,7 @@ class App
$this->container = $diContainer; $this->container = $diContainer;
$this->router = new Router(""); $this->router = new Router("");
$this->frontController = new FrontController($this->router,$this->container); $this->frontController = new FrontController($this->router,$this->container);
$this->session = Session::getInstance(); Session::getInstance();
} }
public function use(IHttpMiddleware $middleware) public function use(IHttpMiddleware $middleware)
@ -142,7 +139,7 @@ class App
$route = $attribute->newInstance(); $route = $attribute->newInstance();
$this->router->addControllerRoute( $this->router->addControllerRoute(
implode('|', $route->getMethods()), $route->getMethods(),
$prefix . $route->getPath(), $prefix . $route->getPath(),
$controllerClass, $controllerClass,
$method->getName(), $method->getName(),

@ -24,6 +24,13 @@ class AppCreator
return $this; return $this;
} }
public function registerSingleton(string $serviceId, $service): self
{
$this->container->set($serviceId, $service, Container::SINGLETON);
$this->services[] = $serviceId;
return $this;
}
/** /**
* Create an instance or perform actions based on the current application environment. * Create an instance or perform actions based on the current application environment.
* *
@ -33,6 +40,7 @@ class AppCreator
{ {
// Check the application environment // Check the application environment
switch (APP_ENV) { switch (APP_ENV) {
case 'console': case 'console':
// Load the Console.php file in case of the 'console' environment // Load the Console.php file in case of the 'console' environment
require_once __DIR__ . '/../console/Console.php'; require_once __DIR__ . '/../console/Console.php';
@ -40,7 +48,6 @@ class AppCreator
case 'development': case 'development':
// Create a new instance of the App class in the 'development' environment // Create a new instance of the App class in the 'development' environment
return new App("HeartTrack", 1, $this->container); return new App("HeartTrack", 1, $this->container);
break;
case 'html': case 'html':
// Load the index.test.php file in case of the 'html' environment // Load the index.test.php file in case of the 'html' environment
require_once __DIR__ . '/index.test.php'; require_once __DIR__ . '/index.test.php';
@ -53,7 +60,6 @@ class AppCreator
} }
function AddControllers($namespacePrefix = 'App\Controller', $pathToControllers = __DIR__ . '/controller'): self function AddControllers($namespacePrefix = 'App\Controller', $pathToControllers = __DIR__ . '/controller'): self
{ {
$controllerFiles = glob($pathToControllers . '/*.php'); $controllerFiles = glob($pathToControllers . '/*.php');
@ -71,7 +77,8 @@ class AppCreator
if ($reflectionClass->isSubclassOf(BaseController::class)) { if ($reflectionClass->isSubclassOf(BaseController::class)) {
// Register in DI container // Register in DI container
$this->container->set($fullClassName, function () use ($fullClassName) { $this->container->set($fullClassName, function () use ($fullClassName) {
$controllerInstance = new $fullClassName(); /** @var $controllerInstance * */
$controllerInstance = $this->container->resolve($fullClassName);
$controllerInstance->setContainer($this->container); $controllerInstance->setContainer($this->container);
return $controllerInstance; return $controllerInstance;
}); });
@ -86,6 +93,11 @@ class AppCreator
{ {
return $this->services; return $this->services;
} }
public function getDicontainer()
{
return $this->container;
}
} }

@ -11,31 +11,45 @@ class Container implements ContainerInterface
{ {
private array $entries = []; private array $entries = [];
const SINGLETON = 'singleton';
const TRANSIENT = 'transient';
public function get(string $id) public function get(string $id)
{ {
if ($this->has($id)) { if ($this->has($id)) {
$entry = $this->entries[$id]; $entry = $this->entries[$id];
if (is_callable($entry)) {
return $entry($this); if ($entry['lifecycle'] === self::SINGLETON) {
if ($entry['instance'] === null) {
$entry['instance'] = $this->resolve($entry['concrete']);
}
return $entry['instance'];
} }
$id = $entry; if (is_callable($entry['concrete'])) {
return $entry['concrete']($this);
}
return $this->resolve($entry['concrete']);
} }
return $this->resolve($id); return $this->resolve($id);
} }
public function has(string $id): bool public function has(string $id): bool
{ {
return isset($this->entries[$id]); return isset($this->entries[$id]);
} }
public function set(string $id, callable|string $concrete): void public function set(string $id, callable|string $concrete, string $lifecycle = self::TRANSIENT): void
{ {
$this->entries[$id] = $concrete; $this->entries[$id] = [
'concrete' => $concrete,
'lifecycle' => $lifecycle,
'instance' => null
];
} }
public function resolve(string $id) public function resolve(string $id)

@ -4,98 +4,96 @@ namespace App\Controller;
use App\Container; use App\Container;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response; use App\Router\Response\Response;
use App\Router\Response\IResponse; use App\Router\Response\IResponse;
use App\Router\Session;
use Manager\UserManager; use Manager\UserManager;
use Shared\Attributes\Route; use Shared\Attributes\Route;
use Shared\Validation; use Shared\Validation;
use Twig\Environment; use Twig\Environment;
use Data\Core\Preferences; use Data\Core\Preferences;
use Shared\Log; use Shared\Log;
use function PHPUnit\Framework\isEmpty;
class AuthController extends BaseController class AuthController extends BaseController
{ {
private UserManager $userMgr;
public function __construct(UserManager $manager){
parent::__construct();
$this->userMgr = $manager;
}
#[Route('/login', name: 'login',methods: ['POST'])] #[Route('/login', name: 'login',methods: ['POST'])]
public function login(IRequest $request): IResponse { public function login(string $email,string $password, IRequest $request): IResponse {
$error = []; $error = [];
try {
$log=Validation::clean_string($request->getBody()['email']);
$mdp=Validation::clean_string($request->getBody()['password']);
} catch (\Throwable $th) {
$error = "Wrong cred";
}
if($this->container->get(UserManager::class)->login($log,$mdp)){ try {
return $this->redirectToRoute('/'); $log=$email; // should check email with verrify email
$mdp=Validation::clean_string($password);
if($this->userMgr->login($log,$mdp)){
return new RedirectResponse('/');
} }
else{ else{
$error [] = "Erreur de connexion. Essayez encore"; $error [] = "Erreur de connexion. Essayez encore";
}
return $this->render('./page/login.html.twig', ['error' => $error]);
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'login_error'=> $error,
]);
} }
#[Route('/log', name: 'baseLog',methods: ['GET'])] // should only cath a type of Exception not all
public function index(IRequest $request): IResponse { } catch (\Throwable $th) {
$error [] =$th->getMessage();
return $this->render('./page/login.html.twig',[ return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'login_error'=> $error,
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]); ]);
} }
#[Route('/register', name: 'register' , methods:['GET'])] }
public function register(IRequest $request): IResponse #[Route('/login', name: 'login2',methods: ['GET'])]
{ public function login2(IRequest $request): IResponse {
if ($request->getMethod() == 'POST') {
$nom = $request->getBody()['nom'];
$prenom = $request->getBody()['prenom'];
$username = $request->getBody()['username'];
$email = $request->getBody()['email'];
$motDePasse = $request->getBody()['motDePasse'];
$sexe = $request->getBody()['sexe'];
$taille = $request->getBody()['taille'];
$poids = $request->getBody()['poids'];
$dateNaissanceStr = $request->getBody()['nom'];
$dateNaissance = new \DateTime($dateNaissanceStr);
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
]);
if (!$dateNaissance) {
throw new \Exception("Date de naissance non valide. Format attendu : YYYY-MM-DD");
} }
#[Route('/register', name: 'register2' , methods:['GET'])]
public function register2(IRequest $request): IResponse{
return $this->render('./page/register.html.twig',[
'css' => $this->preference->getCookie(),
]);
$roleName = $request->getBody()['roleName']; }
#[Route('/register', name: 'register' , methods:['POST'])]
public function register(
string $nom,
string $prenom,
string $username,
string $mail,
string $motDePasse,
string $sexe,
float $taille,
float $poids,
string $dateNaissance,
string $roleName,
IRequest $request): IResponse
{
$error = [];
try {
$registrationData = [ $registrationData = [
'nom' => $nom, 'nom' => $nom,
'prenom' => $prenom, 'prenom' => $prenom,
'username' => $username, 'username' => $username,
'email' => $email, 'email' => $mail,
'sexe' => $sexe, 'sexe' => $sexe,
'taille' => $taille, 'taille' => $taille,
'poids' => $poids, 'poids' => $poids,
@ -103,45 +101,67 @@ class AuthController extends BaseController
'roleName' => $roleName 'roleName' => $roleName
]; ];
try { if ($this->userMgr->register($mail, $motDePasse, $registrationData) ) {
if ($this->container->get(UserManager::class)->register($email, $motDePasse, $registrationData)) { return new RedirectResponse('/');
return $this->redirectToRoute('/');
} else { } else {
$error [] = 'L\'inscription a échoué. Veuillez réessayer.'; $error [] = 'L\'inscription a échoué. Veuillez réessayer.';
return $this->render('./page/register.html.twig',[
'css' => $this->preference->getCookie(),
'register_error'=> $error,
]);
} }
} catch (\Exception $e) { } catch (\Throwable $e) {
$error [] = 'Erreur lors de l\'inscription: ' . $e->getMessage(); $error [] =$e->getMessage();
}
} return $this->render('./page/register.html.twig', ['css' => $this->preference->getCookie(),"register_error" => $error ]);
return $this->render('/register.html.twig');
} }
}
#[Route(path: '/mdp', name: 'mdp', methods: ['POST'])] //string $ancienMotDePasse,string $nouveauMotDePasse,string $confirmerMotDePasse,
public function mdp(string $ancienMotDePasse,string $nouveauMotDePasse,string $confirmerMotDePasse, IRequest $req): Response
#[Route(path: '/forgetPassword', name: 'forget-password2', methods: ['GET'])]
public function forgetPassword2(IRequest $request): IResponse
{ {
return $this->render('./page/password.html.twig',[
'css' => $this->preference->getCookie(),
]);
}
// CONFIRMER LES DONNESS !!!!! IMPORTANT #[Route(path: '/forgetPassword', name: 'forget-password', methods: ['POST'])]
public function forgetPassword(string $mail, IRequest $request): IResponse
{
return $this->render('./page/settings.html.twig',[ return $this->render('./page/password.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]); ]);
} }
#[Route(path: '/logout', name: 'logout', methods: ['POST'])]
public function logout(IRequest $request): IResponse
{
$error = [];
try {
if($this->userMgr->deconnecter()){
return new RedirectResponse('/');
}
else{
$error [] = "Erreur de deconnexion. Essayez encore";
return new RedirectResponse('/');
}
} catch (\Throwable $th) {
$error [] =$th->getMessage();
return new RedirectResponse('/');
}
}

@ -8,13 +8,14 @@ use App\Router\Response\RedirectResponse;
use App\Router\Response\Response; use App\Router\Response\Response;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Shared\Log;
abstract class BaseController abstract class BaseController
{ {
protected Preferences $preference; protected Preferences $preference;
public function __construct(){ public function __construct(){
$this->preference = new Preferences(); $this->preference = new Preferences();
} }
protected ContainerInterface $container; protected ContainerInterface $container;
@ -62,18 +63,5 @@ abstract class BaseController
return new RedirectResponse($url, $status); return new RedirectResponse($url, $status);
} }
protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse
{
return $this->redirect($this->generateUrl($route, $parameters), $status);
}
/*
* TODO : Should hanle ierror if the route is not existing
* */
protected function generateUrl(string $route, array $parameters = []): string
{
return $this->container->get(\App\Router\Router::class)->generate($route, $parameters);
}
} }

@ -332,10 +332,11 @@ class Controller extends BaseController
]); ]);
} }
#[Route(path: '/import', name: 'import', methods: ['GET'])]
public function import(): Response #[Route(path: '/profile', name: 'profile', methods: ['GET'])]
public function profile(): Response
{ {
return $this->render('./page/import.html.twig',[ return $this->render('./page/profile.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => "Doe", 'user' => "Doe",
@ -351,13 +352,15 @@ class Controller extends BaseController
} }
#[Route(path: '/profile', name: 'profile', methods: ['GET'])] #[Route(path: '/psettings', name: 'psettings', methods: ['POST'])]
public function profile(): Response public function psettings(string $nom,string $prenom,string $dateNaissance,string $mail,string $tel, IRequest $req): Response
{ {
return $this->render('./page/profile.html.twig',[
return $this->render('./page/settings.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => "Doe", 'user' => $prenom,
'role' => "Athlète", 'role' => "Athlète",
'friendship' => [], 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
@ -370,15 +373,18 @@ class Controller extends BaseController
} }
#[Route(path: '/psettings', name: 'psettings', methods: ['POST'])]
public function psettings(string $nom,string $prenom,string $dateNaissance,string $mail,string $tel, IRequest $req): Response
#[Route(path: '/pass', name: 'pass', methods: ['GET'])]
public function pass(): Response
{ {
// CONFIRMER LES DONNESS !!!!! IMPORTANT
return $this->render('./page/settings.html.twig',[ return $this->render('./page/password.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => $prenom, 'user' => "Doe",
'role' => "Athlète", 'role' => "Athlète",
'friendship' => [], 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
@ -390,6 +396,26 @@ class Controller extends BaseController
]); ]);
} }
#[Route(path: '/password', name: 'password', methods: ['POST'])]
public function password(string $email, IRequest $req): Response
{
// CONFIRMER LES DONNESS !!!!! IMPORTANT
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
} }

@ -48,6 +48,7 @@ class FrontController {
$this->handleError(404, $e->getMessage()); $this->handleError(404, $e->getMessage());
} }
catch(\Throwable $e){ catch(\Throwable $e){
Log::dd($e->getLine() . $e->getFile() . $e->getMessage() );
$this->handleError(501, $e->getMessage()); $this->handleError(501, $e->getMessage());
} }
} }
@ -65,7 +66,7 @@ class FrontController {
// TODO : Don't work need Antoine help // TODO : Don't work need Antoine help
private function handleError(int $statusCode, $message) : void { private function handleError(int $statusCode, $message) : void {
if (!$this->container->has(\Twig\Environment::class)) { if (!$this->container->has(\Twig\Environment::class)) {
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require ".');
} }
$response = new Response($this->container->get(\Twig\Environment::class)->render('./error/error.html.twig',['title'=> $message , "code" => $statusCode, "name" => $message, "descr" => $message ]),$statusCode); $response = new Response($this->container->get(\Twig\Environment::class)->render('./error/error.html.twig',['title'=> $message , "code" => $statusCode, "name" => $message, "descr" => $message ]),$statusCode);

@ -1,36 +1,95 @@
<?php <?php
// namespace App\Controller; namespace App\Controller;
// use App\Container; use App\Container;
// use App\Router\Request\IRequest; use App\Router\Request\IRequest;
// use App\Router\Response\Response; use App\Router\Response\IResponse;
// use Shared\Attributes\Route; use App\Router\Response\RedirectResponse;
// use Twig\Environment; use App\Router\Response\Response;
// use Data\Core\Preferences; use Manager\ActivityManager;
// use Shared\Log; use Shared\Attributes\Route;
use Twig\Environment;
// class HeartRateController extends BaseController use Data\Core\Preferences;
// { use Shared\Log;
class HeartRateController extends BaseController
// #[Route(path: '/import', name: 'import', methods: ['GET'])] {
// public function import(): Response
// { private ActivityManager $activityMgr;
// return $this->render('./page/import.html.twig',[
// 'css' => $this->preference->getCookie(), public function __construct(ActivityManager $manager)
// 'pp' => "test2", {
// 'user' => "Doe", parent::__construct();
// 'role' => "Athlète", $this->activityMgr = $manager;
// 'friendship' => [], }
// 'analyzes' => [],
// 'mails' => [], #[Route(path: '/import', name: 'import', methods: ['GET'])]
// 'users' => [], public function import(): Response
// 'infoUser' => [], {
// 'exos' => [], return $this->render('./page/import.html.twig', [
// 'member' => [] 'css' => $this->preference->getCookie(),
// ]); 'pp' => "test2",
// } 'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
// } 'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/upload', name: 'upload', methods: ['POST'])]
public function uploadFile(string $activityType, int $effort, IRequest $req): IResponse
{
$error = $this->validateRequest($effort);
if (!empty($error)) {
return $this->renderError($error);
}
$tmp_file = $_FILES['uploaded_file']['tmp_name'];
if (!$this->isValidFile($tmp_file)) {
return $this->renderError(['Failed to get file be sure that you provide the file']);
}
$content = file_get_contents($tmp_file);
try {
if ($this->activityMgr->uploadFile($activityType, 5, $content)) {
return new RedirectResponse('/');
}
} catch (\Exception $e) {
return $this->renderError([$e->getMessage()]);
}
return $this->renderError(['Failed to save activity.']);
}
private function validateRequest(int $effort): array
{
$error = [];
if ($effort < 0 || $effort > 5) {
$error[] = 'Invalid effort level.';
}
$fileExtension = pathinfo($_FILES['uploaded_file']['name'], PATHINFO_EXTENSION);
if ($fileExtension !== 'fit') {
$error[] = 'Invalid file type. Only .fit files are allowed.';
}
return $error;
}
private function isValidFile(string $tmp_file): bool
{
return file_exists($tmp_file) && is_uploaded_file($tmp_file);
}
private function renderError(array $error): Response
{
// Consolidez la logique de rendu ici
return $this->render('./error/error.html.twig', ['title'=> "Failed" , "code" => 400, "name" => "error import", "descr" => $error[0] ], new Response('$error', 400));
}
}

@ -4,15 +4,27 @@ namespace App\Controller;
use App\Container; use App\Container;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response; use App\Router\Response\Response;
use App\Router\Response\IResponse;
use App\Router\Session;
use Manager\UserManager;
use Shared\Attributes\Route; use Shared\Attributes\Route;
use Shared\Validation;
use Twig\Environment; use Twig\Environment;
use Data\Core\Preferences; use Data\Core\Preferences;
use Shared\Log; use Shared\Log;
use function PHPUnit\Framework\isEmpty;
class UserController extends BaseController class UserController extends BaseController
{ {
private UserManager $userMgr;
public function __construct(UserManager $manager){
parent::__construct();
$this->userMgr = $manager;
}
#[Route(path: '/', name: 'home', methods: ['GET'])] #[Route(path: '/', name: 'home', methods: ['GET'])]
public function index(): Response public function index(): Response
@ -75,4 +87,25 @@ class UserController extends BaseController
]); ]);
} }
#[Route(path: '/logout', name: 'logout', methods: ['GET'])]
public function logout(IRequest $request): IResponse
{
$error = [];
try {
if($this->userMgr->deconnecter()){
return new RedirectResponse('/');
}
else{
$error [] = "Erreur de deconnexion. Essayez encore";
return new RedirectResponse('/');
}
} catch (\Throwable $th) {
$error [] =$th->getMessage();
return new RedirectResponse('/');
}
}
} }

@ -1,12 +1,15 @@
<?php <?php
namespace App\Router; namespace App\Router;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
/** /**
* Router class to manage a collection of routes in the application. * Router class to manage a collection of routes in the application.
* It provides functionalities to add routes and check if a given URL matches any of the defined routes. * It provides functionalities to add routes and check if a given URL matches any of the defined routes.
*/ */
class Router { class Router
{
/** /**
* The base path for routing. * The base path for routing.
@ -34,7 +37,8 @@ class Router {
* *
* @param string $path The base path for the router. * @param string $path The base path for the router.
*/ */
public function __construct(string $path = "/PHP/project/index.php") { public function __construct(string $path = "/PHP/project/index.php")
{
$this->path = $path; $this->path = $path;
$this->routes = new \AltoRouter(); $this->routes = new \AltoRouter();
} }
@ -46,7 +50,8 @@ class Router {
* @param Route $route The route object. * @param Route $route The route object.
* @throws \InvalidArgumentException If method is not supported. * @throws \InvalidArgumentException If method is not supported.
*/ */
public function add(string $method, Route $route) { public function add(string $method, Route $route)
{
if (!in_array($method, self::$verbs)) { if (!in_array($method, self::$verbs)) {
throw new \InvalidArgumentException("Method not supported"); throw new \InvalidArgumentException("Method not supported");
} }
@ -55,20 +60,28 @@ class Router {
/** /**
* Adds a route for a controller action. * Adds a route for a controller action.
* * TODO : the problème is that AltoRouter is a map so i can't have mutilple Route just by doing this:(i need to find a logic to resolve this beavior) #[Route('/login', name: 'login',methods: ['POST','GET'])]
* @param string $method The HTTP method. * @param string|array $methods HTTP method.
* @param string $path The path for the route. * @param string $path The path for the route.
* @param mixed $controller The controller object. * @param mixed $controller The controller object.
* @param string $action The action method in the controller. * @param string $action The action method in the controller.
* @param string $name (Optional) The name of the route. * @param string $name (Optional) The name of the route.
* @throws \InvalidArgumentException If method is not supported. * @throws \InvalidArgumentException If method is not supported.
*/ */
public function addControllerRoute(string $method, string $path, $controller, string $action, string $name = '') { public function addControllerRoute(string|array $methods, string $path, $controller, string $action, string $name = '')
{
if (is_string($methods)) {
$methods = [$methods]; // Convert to an array if it's a string
}
foreach ($methods as $method) {
if (!in_array($method, self::$verbs)) { if (!in_array($method, self::$verbs)) {
throw new \InvalidArgumentException("Method not supported"); throw new \InvalidArgumentException("Method not supported");
} }
$this->routes->map($method, $path, [$controller, $action], $name); $this->routes->map($method, $path, [$controller, $action], $name);
} }
}
// TODO: Implement the extractParams method. // TODO: Implement the extractParams method.
// public function extractParams(string $path) {} // public function extractParams(string $path) {}
@ -80,7 +93,8 @@ class Router {
* @param callable $callable The callback function. * @param callable $callable The callback function.
* @param string $name The name of the route. * @param string $name The name of the route.
*/ */
public function get(string $path, callable $callable, $name) { public function get(string $path, callable $callable, $name)
{
$this->routes->map('GET', $path, $callable, $name); $this->routes->map('GET', $path, $callable, $name);
} }
@ -92,7 +106,8 @@ class Router {
* @param IRequest $request The request object. * @param IRequest $request The request object.
* @return array|null The matched route or null if no match. * @return array|null The matched route or null if no match.
*/ */
public function match(IRequest $request): ?array { public function match(IRequest $request): ?array
{
return $this->routes->match($request->getRequestUri(), $request->getMethod()) ?: null; return $this->routes->match($request->getRequestUri(), $request->getMethod()) ?: null;
} }
@ -101,7 +116,8 @@ class Router {
* *
* @return array The array of routes. * @return array The array of routes.
*/ */
public function getRoutes() { public function getRoutes()
{
return []; // TODO: Implement the actual logic to return routes. return []; // TODO: Implement the actual logic to return routes.
} }

@ -111,8 +111,7 @@ class Session
if ( $this->sessionState == self::SESSION_STARTED ) if ( $this->sessionState == self::SESSION_STARTED )
{ {
$this->sessionState = !session_destroy(); $this->sessionState = !session_destroy();
unset( $_SESSION ); session_unset(); // Clear all session variables
return !$this->sessionState; return !$this->sessionState;
} }

@ -2,26 +2,24 @@
namespace App\Router\Middleware; namespace App\Router\Middleware;
use App\Router\Session; use App\Router\Session;
use Network\IAuthService;
use Shared\Log; use Shared\Log;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse; use App\Router\Response\RedirectResponse;
class AuthMiddleware extends Middleware { class AuthMiddleware extends Middleware {
public function handle(IRequest $request, callable $next) {
// if (isset($_SESSION['user'])) {
// $resp =new RedirectResponse("/");
// $resp->send();
// exit;
// }
// La page nest pas redirigée correctement
// Firefox a détecté que le serveur redirige la demande pour cette adresse dune manière qui naboutira pas. private IAuthService $auth;
public function __construct(IAuthService $auth) {
$this->auth = $auth;
}
public function handle(IRequest $request, callable $next) {
$excludedUrls = ['/login', '/register','/forgetPassword'];
// La cause de ce problème peut être la désactivation ou le refus des cookies. if ($this->auth->getCurrentUser() === null && !in_array($request->getRequestUri(), $excludedUrls)) {
// if (!isset($_SESSION['user'])) { $resp = new RedirectResponse("/login");
// $resp =new RedirectResponse("/log"); $resp->send();
// $resp->send(); exit;
// exit; }
// }
return parent::handle($request, $next); return parent::handle($request, $next);
} }
} }

@ -2,6 +2,9 @@
namespace App\Router\Response; namespace App\Router\Response;
use App\Router\Session;
use Shared\Log;
class RedirectResponse implements IResponse class RedirectResponse implements IResponse
{ {
private $content; private $content;
@ -49,6 +52,7 @@ class RedirectResponse implements IResponse
public function send(): void public function send(): void
{ {
http_response_code($this->statusCode); http_response_code($this->statusCode);
foreach ($this->headers as $name => $value) { foreach ($this->headers as $name => $value) {

@ -1,6 +1,8 @@
<?php <?php
namespace App\Router\Response; namespace App\Router\Response;
use Shared\Log;
class Response implements IResponse { class Response implements IResponse {
private string $content; private string $content;
private int $statusCode; private int $statusCode;

@ -34,15 +34,10 @@
<input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" /> <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />
<label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label> <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>
</div> </div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="password.html">Mot de passe oublié ?</a>
<a class="btn btn-primary" href="index.html">Se connecter</a>
</div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3">
<div class="small"><a href="register.html">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div>
</div> </div>
</div> </div>
</div> </div>

@ -7,6 +7,8 @@
<meta name="description" content="Accueil" /> <meta name="description" content="Accueil" />
<meta name="author" content="PINAGOT Antoine" /> <meta name="author" content="PINAGOT Antoine" />
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" /> <link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" />
<link href="/css/{% block css %}style{% endblock %}.css" rel="stylesheet" /> <link href="/css/{% block css %}style{% endblock %}.css" rel="stylesheet" />
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script> <script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>

@ -3,5 +3,12 @@
{% block title %}{{code}} : {{title}}{% endblock %} {% block title %}{{code}} : {{title}}{% endblock %}
{% block nb %}<h1 class="display-1">{{code}}</h1>{% endblock %} {% block nb %}
{% if code == 404 %}
<img class="mb-4 img-error" src="assets/img/error-404-monochrome.svg"/>
{% else %}
<h1 class="display-1">{{code}}</h1>
{% endif %}
{% endblock %}
{% block descr %}{{descr}}{% endblock %} {% block descr %}{{descr}}{% endblock %}

@ -12,30 +12,53 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Importer</h1> <h1 class="mt-4">Importer</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="home.html">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Importer</li> <li class="breadcrumb-item active">Importer</li>
</ol> </ol>
<div class="flex items-center justify-center">
<div class="row"> <div class="sm:max-w-lg w-full p-10 bg-white rounded-xl z-10 ">
<div class="col"> <div class="text-center">
<div class="card mb-4"> <h2 class="mt-5 text-3xl font-bold text-gray-900">
<div class="card-header"> Importer un fichier .fit !
<img src="/assets/img/bupload.png"></i> </h2>
Importer un fichier .fit <p class="mt-2 text-sm text-gray-400">Let's go</p>
</div> </div>
<div class="card-body"> <form class="mt-8 space-y-3" action="/upload" method="POST" enctype="multipart/form-data">
<div class="grid grid-cols-1 space-y-2">
<div style="text-align:center; margin-bottom: 15px;"> <label class="text-sm font-bold text-gray-500 tracking-wide">Veuillez renseigner le type d'activité</label>
<label for="file-input"> <input class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500" type="text" name="activityType" placeholder="Course à pied">
<img src="/assets/img/uploadW.svg"/> </div>
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Effort Level (0-5)</label>
<input class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500" type="number" name="effort" min="0" max="5" placeholder="Enter effort level (0-5)">
</div>
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Attach Document</label>
<div class="flex items-center justify-center w-full">
<label class="flex flex-col rounded-lg border-4 border-dashed w-full h-60 p-10 group text-center cursor-pointer">
<div class="h-full w-full text-center flex flex-col items-center justify-center items-center ">
<div class="flex flex-auto max-h-48 w-2/5 mx-auto -mt-10">
<img class="has-mask h-36 object-center" src="https://img.freepik.com/free-vector/image-upload-concept-landing-page_52683-27130.jpg?size=338&ext=jpg" alt="freepik image">
</div>
<p class="pointer-none text-gray-500 "><span class="text-sm">Drag and drop</span> files here <br /> or
<span class="text-blue-600 hover:underline">select a file</span>
from your computer</p>
</div>
<input type="file" class="hidden" id="file-input" name="uploaded_file">
</label> </label>
<form action="/analyses" method="post"> <p id="file-name-display" class="text-sm text-gray-500"></p>
<input id="file-input" type="file" name="fileToUpload" value=""style="visibility: hidden; width:0; height:0;"/>
<input type="submit" value="Soumettre le fichier" name="submit"/>
</form>
</div> </div>
</div> </div>
<p class="text-sm text-gray-300">
<span>File type: .fit</span>
</p>
<div class="flex justify-center">
<button type="submit" class="my-5 w-3/4 flex justify-center bg-blue-500 text-gray-100 p-4 rounded-full tracking-wide
font-semibold focus:outline-none focus:shadow-outline hover:bg-blue-600 shadow-lg cursor-pointer transition ease-in duration-300">
Upload
</button>
</div> </div>
</form>
</div> </div>
</div> </div>
</div> </div>

@ -0,0 +1 @@
<a href="/log">Se connecter</button>

@ -11,27 +11,35 @@
<div class="card shadow-lg border-0 rounded-lg mt-5"> <div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div> <div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div>
<div class="card-body"> <div class="card-body">
<form> {% if login_error %}
{% for value in login_error %}
<div class="alert alert-danger" role="alert">
{{ value }}
</div>
{% endfor %}
{% endif %}
<form method="post" action="/login">
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" /> <input class="form-control" id="email" name="email" type="text" placeholder="Nom d'utilisateur" />
<label for="inputEmail">Adresse eMail</label> <label for="email">Nom d'utilisateur</label>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="inputPassword" type="password" placeholder="Mot de passe" /> <input class="form-control" id="password" name="password" type="password" placeholder="Mot de passe" />
<label for="inputPassword">Mot de passe</label> <label for="password">Mot de passe</label>
</div> </div>
<div class="form-check mb-3"> <div class="form-check mb-3">
<input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" /> <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />
<label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label> <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>
</div> </div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0"> <div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="password.html">Mot de passe oublié ?</a> <a class="small" href="/forgetPassword">Mot de passe oublié ?</a>
<a class="btn btn-primary" href="index.html">Se connecter</a> <button class="btn btn-primary" type="submit">Se connecter</button>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3"> <div class="card-footer text-center py-3">
<div class="small"><a href="register.html">Besoin d'un compte ? Inscrivez-vous !</a></div> <div class="small"><a href="/register">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div> </div>
</div> </div>
</div> </div>

@ -0,0 +1,33 @@
{% extends "authbase.html.twig" %}
{% block css %}{{css}}{% endblock %}
{% block title %}Mot de passe oublié - HearthTrack{% endblock %}
{% block main %}
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Récupération du mot de passe</h3></div>
<div class="card-body">
<div class="small mb-3 text-muted">Entrez votre adresse eMail pour recevoir un lien pour changer de mot de passe</div>
<form method="post" action="/">
<div class="form-floating mb-3">
<input class="form-control" id="email" name="email" type="email" placeholder="name@example.com" />
<label for="email">Adresse eMail</label>
</div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="/login">Retour à la connexion</a>
<button class="btn btn-primary" type="submit">Réinitialiser votre mot de passe</button>
</div>
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="/register">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

@ -11,82 +11,105 @@
<div class="card shadow-lg border-0 rounded-lg mt-5"> <div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Créer un compte</h3></div> <div class="card-header"><h3 class="text-center font-weight-light my-4">Créer un compte</h3></div>
<div class="card-body"> <div class="card-body">
<form> {# Display error message if register_error is set #}
{% if register_error %}
{% for value in register_error %}
<div class="alert alert-danger" role="alert">
{{ value }}
</div>
{% endfor %}
{% endif %}
<form method="post" action="/register">
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputFirstName" type="text" placeholder="Entrez votre nom" /> <input class="form-control" id="nom" name="nom" type="text" placeholder="Entrez votre nom" />
<label for="inputFirstName">Nom de famille</label> <label for="nom">Nom de famille</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating"> <div class="form-floating">
<input class="form-control" id="inputLastName" type="text" placeholder="Entrez votre prénom" /> <input class="form-control" id="prenom" name="prenom" type="text" placeholder="Entrez votre prénom" />
<label for="inputLastName">Prénom</label> <label for="prenom">Prénom</label>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputUsername" type="text" placeholder="Entrez votre pseudonyme" /> <input class="form-control" id="username" name="username" type="text" placeholder="Entrez votre pseudonyme" />
<label for="inputFirstName">Nom d'utilisateur</label> <label for="username">Nom d'utilisateur</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label for="sexe" >Sexe:</label>
<div class="form-floating"> <div class="form-floating">
<label for="inputLastName">Sexe</label> <select id="sexe" name="sexe">
<select id="gender" name="gender"> <option value="M">Homme</option>
<option value="male">Homme</option> <option value="H">Femme</option>
<option value="female">Femme</option> <option value="M">Ne se prononce pas</option>
<option value="unknown">Ne se prononce pas</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" /> <input class="form-control" id="mail" name="mail" type="mail" placeholder="nom@exemple.com" />
<label for="inputEmail">Adresse eMail</label> <label for="mail">Adresse eMail</label>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="inputDateNaissance" type="date" placeholder="" /> <input class="form-control" id="dateNaissance" name="dateNaissance" type="date" placeholder="" />
<label for="inputEmail">Date de naissance</label> <label for="dateNaissance">Date de naissance</label>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputTaille" type="text" placeholder="Entrez votre taille" /> <input class="form-control" id="taille" name="taille" type="text" placeholder="Entrez votre taille" />
<label for="inputPassword">Taille</label> <label for="taille">Taille</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputPoids" type="text" placeholder="Entrez votre poids" /> <input class="form-control" id="poids" name="poids" type="text" placeholder="Entrez votre poids" />
<label for="inputPasswordConfirm">Poids</label> <label for="poids">Poids</label>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputPassword" type="password" placeholder="Créez un mot de passe" /> <input class="form-control" id="motDePasse" name="motDePasse" type="password" placeholder="Créez un mot de passe" />
<label for="inputPassword">Mot de passe</label> <label for="motDePasse">Mot de passe</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputPasswordConfirm" type="password" placeholder="Confirmez votre mot de passe" /> <input class="form-control" id="confirmMdp" name="confirmMdp" type="password" placeholder="Confirmez votre mot de passe" />
<label for="inputPasswordConfirm">Confirmer le mot de passe</label> <label for="confirmMdp">Confirmer le mot de passe</label>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3">
<div class="col-md-6">
<label for="roleName" >Role:</label>
<div class="form-floating">
<select id="roleName" name="roleName">
<option value="Athlete">Athlete</option>
<option value="Coach">Coach</option>
</select>
</div>
</div>
</div>
<div class="mt-4 mb-0"> <div class="mt-4 mb-0">
<div class="d-grid"><a class="btn btn-primary btn-block" href="login.html.twig">Créer un compte</a></div> <div class="d-grid">
<button type="submit" class="btn btn-primary btn-block">Créer un compte</button>
</div>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3"> <div class="card-footer text-center py-3">
<div class="small"><a href="login.html.twig">Avez-vous déjà un compte ? Connectez-vous ?</a></div> <div class="small"><a href="/login">Avez-vous déjà un compte ? Connectez-vous ?</a></div>
</div> </div>
</div> </div>
</div> </div>

@ -759,7 +759,13 @@ function profileMenu(Model $model)
do { do {
$effort = trim(fgets(STDIN)); $effort = trim(fgets(STDIN));
} while ($effort < 0 || $effort > 5); } while ($effort < 0 || $effort > 5);
try {
$isAddActivity = $model->activityMgr->uploadFile($typeActivity, $effort, $passFile); $isAddActivity = $model->activityMgr->uploadFile($typeActivity, $effort, $passFile);
}catch (\Throwable $exception){
echo $exception;
}
echo $isAddActivity ? "Activité ajoutée avec succès" : "Erreur lors de l'ajout de l'activité"; echo $isAddActivity ? "Activité ajoutée avec succès" : "Erreur lors de l'ajout de l'activité";
case '0': case '0':
return; return;
@ -790,7 +796,7 @@ while (true) {
}*/ }*/
break; break;
case '2': // S'inscrire case '2': // S'inscrire
if($model->userMgr->login("bruce.lee@example.com", "hello321")) if($model->userMgr->login("bruce.lee@example.com", "password123"))
$loggedIn = true; $loggedIn = true;
// if (registerUser($model)) { // if (registerUser($model)) {
// $loggedIn = true; // $loggedIn = true;

@ -2,15 +2,19 @@
namespace Data\Core; namespace Data\Core;
use Shared\Log;
class Preferences { class Preferences {
private String $cookie; private string $cookie;
private Array $theme; private array $theme;
public function __construct(){ public function __construct(){
if (isset($_COOKIE['preferences'])){ if (isset($_COOKIE['preferences'])){
$this->cookie = $_COOKIE['preferences']; $this->cookie = $_COOKIE['preferences'];
} else { } else {
$this->cookie = setcookie('preferences', 'base_theme', time()+(3600*24)*7); if(setcookie('preferences', 'base_theme', time()+(3600*24)*7)){
$this->cookie = 'base_theme';
}
} }
$this->theme = array( $this->theme = array(
'base_theme', 'base_theme',
@ -19,7 +23,7 @@
); );
} }
public function majCookie(String $maj){ public function majCookie(string $maj){
try{ try{
foreach($this->theme as $t){ foreach($this->theme as $t){
$this->cookie = $maj; $this->cookie = $maj;
@ -30,8 +34,8 @@
} }
} }
public function getCookie():String{ public function getCookie():string{
return $this->cookie; return $this->cookie ?? "base_theme";
} }
} }

@ -1,34 +1,42 @@
<?php <?php
namespace Data\Core; namespace Network;
use App\Router\Session;
use Model\User; use Model\User;
use Model\Athlete; use Model\Athlete;
use Model\CoachAthlete; use Model\CoachAthlete;
use Repository\IUserRepository; use Repository\IUserRepository;
use Shared\IHashPassword; use Shared\IHashPassword;
use Shared\Log;
class AuthService implements IAuthService { const USER = 'USER';
class AuthService implements IAuthService
{
private IUserRepository $userRepository; private IUserRepository $userRepository;
private IHashPassword $passwordHacher; private IHashPassword $passwordHacher;
private ?User $currentUser = null; private ?User $currentUser = null;
public function __construct(IUserRepository $userRepository, IHashPassword $passwordHacher) { public function __construct(IUserRepository $userRepository, IHashPassword $passwordHacher)
{
$this->userRepository = $userRepository; $this->userRepository = $userRepository;
$this->passwordHacher = $passwordHacher; $this->passwordHacher = $passwordHacher;
} }
public function login(string $email, string $password): bool { public function login(string $email, string $password): bool
{
$user = $this->userRepository->getItemByEmail($email); $user = $this->userRepository->getItemByEmail($email);
if ($user === null || !$this->validatePassword($password, $user->getPasswordHash())) { if ($user === null || !$this->passwordHacher->isPasswordValid( $user->getMotDePasse(),$password)) {
return false; return false;
} }
$this->currentUser = $user; $this->currentUser = $user;
// Add session handling logic here Session::getInstance()->__set(USER, $this->currentUser->getId());
return true; return true;
} }
public function register(string $email, string $password, array $data): bool {
public function register(string $email, string $password, $data): bool
{
if ($this->userRepository->getItemByEmail($email)) { if ($this->userRepository->getItemByEmail($email)) {
throw new \Exception('User already exists'); throw new \Exception('User already exists');
} }
@ -37,7 +45,6 @@ class AuthService implements IAuthService {
$prenom = $data['prenom']; $prenom = $data['prenom'];
$username = $data['username']; $username = $data['username'];
$nom = $data['nom']; $nom = $data['nom'];
$email = $data['email'];
$sexe = $data['sexe']; $sexe = $data['sexe'];
$taille = $data['taille']; $taille = $data['taille'];
$poids = $data['poids']; $poids = $data['poids'];
@ -46,11 +53,10 @@ class AuthService implements IAuthService {
$role = null; $role = null;
if ($roleName == "Coach") { if ($roleName == "Coach") {
$role = new CoachAthlete(); $role = new CoachAthlete();
} } else if ($roleName == "Athlete") {
else if($roleName == "Athlete"){
$role = new Athlete(); $role = new Athlete();
} }
// Create a new user instance (you should expand on this with more data as needed)
$user = new User( $user = new User(
random_int(0, 100), random_int(0, 100),
$nom, $nom,
@ -67,20 +73,26 @@ class AuthService implements IAuthService {
); );
$this->userRepository->addItem($user); $this->userRepository->addItem($user);
$this->currentUser = $user; $this->currentUser = $user;
// Add session handling logic here Session::getInstance()->__set(USER,$this->currentUser->getId());
return true; return true;
} }
public function logout(): void { public function logoutUser(): bool
{
$this->currentUser = null; $this->currentUser = null;
// Add session handling logic here Session::getInstance()->destroy();
return true;
} }
public function getCurrentUser(): ?User { public function getCurrentUser(): ?User
{
if (!empty(Session::getInstance()->__get(USER)) && $this->currentUser === null) {
$this->currentUser = $this->userRepository->getItemById(Session::getInstance()->__get(USER));
}
return $this->currentUser; return $this->currentUser;
} }
private function validatePassword(string $password, string $hash): bool {
// Implement password validation logic (e.g., using password_verify if using bcrypt)
}
} }

@ -33,18 +33,18 @@ interface IAuthService {
/** /**
* Register a new user. * Register a new user.
* *
* @param string $username The username of the new user. * @param string $emailUser The emailUser of the new user.
* @param string $password The password of the new user. * @param string $password The password of the new user.
* @param $data other data {undefined} for the moment. * @param $data other data {undefined} for the moment.
* *
* @return bool True if registration is successful, false otherwise. * @return bool True if registration is successful, false otherwise.
*/ */
public function register(string $username, string $password, $data): bool; public function register(string $emailUser, string $password, $data): bool;
/** /**
* Logout the currently authenticated user. * Logout the currently authenticated user.
* *
* @return void * @return bool
*/ */
public function logoutUser(): bool; public function logoutUser(): bool;

@ -27,7 +27,7 @@ class Activity
private float $variability; private float $variability;
private float $variance; private float $variance;
private float $standardDeviation; private float $standardDeviation;
private int $average; private float $average;
private int $maximum; private int $maximum;
private int $minimum; private int $minimum;
private float $avrTemperature; private float $avrTemperature;

@ -8,12 +8,14 @@
* *
* @package manager * @package manager
*/ */
namespace Manager; namespace Manager;
use adriangibbons\phpFITFileAnalysis; use adriangibbons\phpFITFileAnalysis;
use Exception; use Exception;
use Model\Activity; use Model\Activity;
use Network\IAuthService; use Network\IAuthService;
use Shared\Log;
use Stub\AuthService; use Stub\AuthService;
/** /**
@ -27,6 +29,12 @@ class ActivityManager
*/ */
private IAuthService $authService; private IAuthService $authService;
/**
* @var DataManager
*/
private DataManager $dataManager;
/** /**
* Constructeur de la classe ActivityManager. * Constructeur de la classe ActivityManager.
* *
@ -35,6 +43,7 @@ class ActivityManager
public function __construct(DataManager $dataManager, IAuthService $authService) public function __construct(DataManager $dataManager, IAuthService $authService)
{ {
$this->authService = $authService; $this->authService = $authService;
$this->dataManager = $dataManager;
} }
/** /**
@ -63,9 +72,8 @@ class ActivityManager
// Conversion des données en format JSON // Conversion des données en format JSON
$jsonFitData = json_encode($fitData, JSON_PRETTY_PRINT); $jsonFitData = json_encode($fitData, JSON_PRETTY_PRINT);
// Enregistrement du fichier JSON // Enregistrement du fichier JSON
file_put_contents('/Users/Perederii/SAE/git/Web/Sources/src/data/model/fitFileSaver/jsonFiles/ActivitySave.json', $jsonFitData); file_put_contents('./you.json', $jsonFitData);
return true; return true;
} catch (\Exception $e) { } catch (\Exception $e) {
@ -85,12 +93,13 @@ class ActivityManager
* @return bool Retourne true en cas de succès, sinon false. * @return bool Retourne true en cas de succès, sinon false.
* @throws Exception En cas d'erreur lors du téléchargement, du traitement ou de l'enregistrement des données. * @throws Exception En cas d'erreur lors du téléchargement, du traitement ou de l'enregistrement des données.
*/ */
public function uploadFile($type, $effortRessenti, $file_path_or_data, ?array $options = null): bool public function uploadFile(string $type, int $effortRessenti, string $file_path_or_data, ?array $options = null): bool
{ {
try { try {
// Vérification des options par défaut // Vérification des options par défaut
if (empty($options)) { if (empty($options)) {
$options = [ $options = [
'input_is_data' => true,
'fix_data' => ['all'], 'fix_data' => ['all'],
'data_every_second' => false, 'data_every_second' => false,
'units' => 'metric', 'units' => 'metric',
@ -99,7 +108,6 @@ class ActivityManager
'overwrite_with_dev_data' => false 'overwrite_with_dev_data' => false
]; ];
} }
// Ouverture du fichier FIT // Ouverture du fichier FIT
if (!($monFichierFit = new phpFITFileAnalysis($file_path_or_data, $options))) { if (!($monFichierFit = new phpFITFileAnalysis($file_path_or_data, $options))) {
throw new Exception("Problème lors de l'ouverture du fichier FIT"); throw new Exception("Problème lors de l'ouverture du fichier FIT");
@ -128,9 +136,14 @@ class ActivityManager
$standardDeviation = number_format(sqrt($variance), 2); $standardDeviation = number_format(sqrt($variance), 2);
$maximum = max($heartRateList); $maximum = max($heartRateList);
$minimum = min($heartRateList); $minimum = min($heartRateList);
if(isset($monFichierFit->data_mesgs['record']['temperature'])){
// Extraction de la température moyenne (si disponible
$temperatureList = $monFichierFit->data_mesgs['record']['temperature']; $temperatureList = $monFichierFit->data_mesgs['record']['temperature'];
$averageTemperature = (!empty($temperatureList)) ? number_format(array_sum($temperatureList) / count($temperatureList), 1) : -200; $averageTemperature = (!empty($temperatureList)) ? number_format(array_sum($temperatureList) / count($temperatureList), 1) : -200;
}
else{
$averageTemperature = -200;
}
$isPaused = count($monFichierFit->isPaused()) > 0; $isPaused = count($monFichierFit->isPaused()) > 0;
@ -150,16 +163,23 @@ class ActivityManager
$averageTemperature, $averageTemperature,
$isPaused $isPaused
); );
// $this->dataManager->activityRepository->add($newActivity);
// if ($this->saveFitFileToJSON($monFichierFit)) {
// Ajout de l'activité et enregistrement du fichier FIT en JSON // Ajout de l'activité et enregistrement du fichier FIT en JSON
if ($this->authService->getCurrentUser()->getRole()->addActivity($newActivity) && $this->saveFitFileToJSON($monFichierFit)) { if ($this->authService->getCurrentUser()->getRole()->addActivity($newActivity)) {
return true; return true;
} }
} catch (\Exception $e) { // }
return false;
}
catch(\Exception $e){
echo $e; echo $e;
} }
return false; return false;
} }
} }
?> ?>

@ -11,6 +11,7 @@ abstract class DataManager {
public IRelationshipRequestRepository $relationshipRequestRepository; public IRelationshipRequestRepository $relationshipRequestRepository;
public ITrainingRepository $trainingRepository; public ITrainingRepository $trainingRepository;
public INotificationRepository $notificationRepository; public INotificationRepository $notificationRepository;
public IActivityRepository $activityRepository;
} }
?> ?>

@ -10,7 +10,7 @@ use Network\IAuthService;
use Network\IFriendRequestService; use Network\IFriendRequestService;
use Shared\Validation; use Shared\Validation;
use Stub\UserRepository; use Stub\UserRepository;
use Shared\Log;
class UserManager class UserManager
{ {
private IAuthService $authService; private IAuthService $authService;
@ -48,7 +48,6 @@ class UserManager
return false; return false;
} }
if ($this->authService->login($emailUser, $passwordUser)) { if ($this->authService->login($emailUser, $passwordUser)) {
$this->currentUser = $this->authService->getCurrentUser(); $this->currentUser = $this->authService->getCurrentUser();
// Check if the current user is correctly set // Check if the current user is correctly set
@ -146,6 +145,10 @@ class UserManager
} }
// NEED TO PERSIST // NEED TO PERSIST
/**
* @throws \Exception
*/
public function register($loginUser, $passwordUser, $data): bool public function register($loginUser, $passwordUser, $data): bool
{ {
// foreach ($data as $entry) { // foreach ($data as $entry) {
@ -155,6 +158,21 @@ class UserManager
// } // }
// } // }
$dateNaissance = new \DateTime($data['dateNaissance']);
$dateActuelle = new \DateTime();
// Vérifier si la date est dans le futur
if ($dateNaissance > $dateActuelle) {
throw new \Exception("La date de naissance ne peut pas être dans le futur.");
}
// Vérifier l'âge minimum (par exemple, 18 ans)
$ageMinimum = new \DateTime('-10 years');
if ($dateNaissance > $ageMinimum) {
throw new \Exception("Vous devez avoir au moins 18 ans pour vous inscrire.");
}
$data['dateNaissance'] = $dateNaissance;
$roleName = $data['roleName']; $roleName = $data['roleName'];
if ($roleName !== "Athlete" && $roleName !== "Coach") { if ($roleName !== "Athlete" && $roleName !== "Coach") {
throw new \Exception("Rôle non valide"); throw new \Exception("Rôle non valide");

@ -5,6 +5,8 @@ interface IUserRepository extends IGenericRepository {
public function addFriend(int $user1,int $user2); public function addFriend(int $user1,int $user2);
public function deleteFriend(int $user1,int $user2); public function deleteFriend(int $user1,int $user2);
public function getItemByEmail(string $email);
} }
?> ?>

@ -11,11 +11,11 @@ class UserRepository implements IUserRepository {
private array $users = []; private array $users = [];
public function __construct() { public function __construct() {
$this->users[] = new User(1, "Doe", "John", "Doe","john.doe@example.com", "password123", 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete()); $this->users[] = new User(1, "Doe", "John", "Doe","john.doe@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete());
$this->users[] = new User(2, "Smith", "Jane","Smith", "jane.smith@example.com", "secure456", 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete()); $this->users[] = new User(2, "Smith", "Jane","Smith", "jane.smith@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete());
$this->users[] = new User(3, "Martin", "Paul","Martin", "paul.martin@example.com", "super789", 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete()); $this->users[] = new User(3, "Martin", "Paul","Martin", "paul.martin@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete());
$this->users[] = new User(4, "Brown", "Anna","Brown", "anna.brown@example.com", "test000", 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete()); $this->users[] = new User(4, "Brown", "Anna","Brown", "anna.brown@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete());
$this->users[] = new User(5, "Lee", "Bruce","Lee", "bruce.lee@example.com", "hello321", 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete()); $this->users[] = new User(5, "Lee", "Bruce","Lee", "bruce.lee@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
} }
public function getItemById(int $id): ?User { public function getItemById(int $id): ?User {

@ -1,5 +1,7 @@
<?php <?php
namespace Stub; namespace Stub;
use Model\Athlete; use Model\Athlete;
use Model\CoachAthlete; use Model\CoachAthlete;
@ -8,30 +10,37 @@ use Repository\IUserRepository;
use Shared\Exception\NotImplementedException; use Shared\Exception\NotImplementedException;
use Network\IAuthService; use Network\IAuthService;
use Shared\IHashPassword; use Shared\IHashPassword;
use Shared\Log;
use Stub\UserRepository; use Stub\UserRepository;
class AuthService implements IAuthService {
class AuthService implements IAuthService
{
private IUserRepository $userRepository; private IUserRepository $userRepository;
private IHashPassword $passwordHacher; private IHashPassword $passwordHacher;
private ?User $currentUser; private ?User $currentUser;
public function __construct(UserRepository $userRepository, IHashPassword $passwordHacher) { public function __construct(UserRepository $userRepository, IHashPassword $passwordHacher)
{
$this->userRepository = $userRepository; $this->userRepository = $userRepository;
$this->passwordHacher = $passwordHacher; $this->passwordHacher = $passwordHacher;
} }
public function login(string $emailUser,string $password): bool { public function login(string $emailUser, string $password): bool
{
$user = $this->userRepository->getItemByEmail($emailUser); $user = $this->userRepository->getItemByEmail($emailUser);
if (!$user instanceof User) { if (!$user instanceof User) {
throw new \Exception('Unable to find user with that name'); throw new \Exception('Unable to find user with that name');
} }
if ($user->isValidPassword($password)) { if (!$this->passwordHacher->isPasswordValid($user->getMotDePasse(), $password)) {
return false;
}
$this->currentUser = $user; $this->currentUser = $user;
return true; return true;
}
return false;
} }
public function register(string $username, string $password, $data): bool public function register(string $username, string $password, $data): bool
{ {
@ -55,8 +64,7 @@ class AuthService implements IAuthService {
$role = null; $role = null;
if ($roleName == "Coach") { if ($roleName == "Coach") {
$role = new CoachAthlete(); $role = new CoachAthlete();
} } else if ($roleName == "Athlete") {
else if($roleName == "Athlete"){
$role = new Athlete(); $role = new Athlete();
} }
$user = new User( $user = new User(

@ -2,6 +2,8 @@
namespace Shared; namespace Shared;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use InvalidArgumentException;
/** /**
* Responsible for resolving the arguments passed to a controller action. * Responsible for resolving the arguments passed to a controller action.
*/ */
@ -14,7 +16,7 @@ class ArgumentControllerResolver implements IArgumentResolver{
* @param callable $controller The controller callable. * @param callable $controller The controller callable.
* @return array An array of resolved arguments. * @return array An array of resolved arguments.
* @throws \ReflectionException If the controller method does not exist. * @throws \ReflectionException If the controller method does not exist.
* @throws \InvalidArgumentException If an argument cannot be resolved. * @throws InvalidArgumentException If an argument cannot be resolved.
*/ */
public function getArguments(IRequest $request, callable $controller): array public function getArguments(IRequest $request, callable $controller): array
{ {
@ -27,10 +29,10 @@ class ArgumentControllerResolver implements IArgumentResolver{
$reflectionMethod = new \ReflectionMethod($className, $methodName); $reflectionMethod = new \ReflectionMethod($className, $methodName);
} else { } else {
// Handle other types of callables if needed // Handle other types of callables if needed
throw new \InvalidArgumentException("Invalid controller callable format."); throw new InvalidArgumentException("Invalid controller callable format.");
} }
} catch (\ReflectionException $e) { } catch (\ReflectionException $e) {
throw new \InvalidArgumentException("Controller method error: " . $e->getMessage()); throw new InvalidArgumentException("Controller method error: " . $e->getMessage());
} }
$args = []; $args = [];
@ -42,11 +44,10 @@ class ArgumentControllerResolver implements IArgumentResolver{
$name = $param->getName(); $name = $param->getName();
$value = $this->getFromRequest($name, $request); $value = $this->getFromRequest($name, $request);
if ($value === null && $param->isDefaultValueAvailable()) { if ($value === null && $param->isDefaultValueAvailable()) {
$value = $param->getDefaultValue(); $value = $param->getDefaultValue();
} elseif ($value === null) { } elseif ($value === null) {
throw new \InvalidArgumentException("Missing argument: $name"); throw new InvalidArgumentException("Missing argument: $name");
} }
$args[] = $value; $args[] = $value;

@ -26,7 +26,7 @@ final class Validation {
* @throws Exception Si la chaîne n'est pas valide (tentative d'injection de code). * @throws Exception Si la chaîne n'est pas valide (tentative d'injection de code).
*/ */
public static function val_string(string $string) : bool { public static function val_string(string $string) : bool {
if (filter_var($string, FILTER_SANITIZE_STRING) !== $string) { if (!$string) {//filter_var($string, FILTER_SANITIZE_STRING) !== $string
throw new Exception("$string n'est pas valide. Tentative d'injection de code (attaque sécurité)!"); throw new Exception("$string n'est pas valide. Tentative d'injection de code (attaque sécurité)!");
} else { } else {
return true; return true;
@ -101,7 +101,7 @@ final class Validation {
* @return string La chaîne nettoyée. * @return string La chaîne nettoyée.
*/ */
public static function clean_string(string $string) : string { public static function clean_string(string $string) : string {
return filter_var($string, FILTER_SANITIZE_STRING); return filter_var($string);
} }
/** /**

@ -1,4 +1,5 @@
<?php <?php
use Shared\Log;
class AltoRouter { class AltoRouter {
@ -100,6 +101,8 @@ class AltoRouter {
public function generate($routeName, array $params = array()) { public function generate($routeName, array $params = array()) {
// Check if named route exists // Check if named route exists
if(!isset($this->namedRoutes[$routeName])) { if(!isset($this->namedRoutes[$routeName])) {
throw new \Exception("Route '{$routeName}' does not exist."); throw new \Exception("Route '{$routeName}' does not exist.");
} }

Loading…
Cancel
Save