Commit 01625f20 authored by quentin.vrel's avatar quentin.vrel

tp4 18/11/2020

parent 5ea03f1e
...@@ -12,7 +12,7 @@ class AutoLoader { ...@@ -12,7 +12,7 @@ class AutoLoader {
private function load($className) { private function load($className) {
$_model=["Model", "Role", "User"]; $_model=["Model", "Role", "User"];
$_classes=["DatabasePDO", "Dispatcher", "Request", "Response"]; $_classes=["DatabasePDO", "Dispatcher", "Request", "Response"];
$_controller=["Controller", "DefaultController", "UserController"]; $_controller=["Controller", "DefaultController", "UserController", "LoginController", "ValidateTokenController"];
if(in_array($className, $_model)){ if(in_array($className, $_model)){
require_once "model/$className.class.php"; require_once "model/$className.class.php";
......
...@@ -69,13 +69,8 @@ class Request { ...@@ -69,13 +69,8 @@ class Request {
} }
public function initData() { public function initData() {
if ($this->getHttpMethod() === 'PUT'){ if ($this->getHttpMethod() === 'PUT' || $this->getHttpMethod() === 'POST'){
$this->data = ""; $this->data = json_decode(file_get_contents("php://input"), true);
$stream = fopen("php://input", "r");
$next_byte=fread($stream, '1024');
$this->data .= $next_byte;
fclose($stream);
$this->data=json_decode($this->data, TRUE);
} }
} }
...@@ -89,6 +84,19 @@ class Request { ...@@ -89,6 +84,19 @@ class Request {
public function getData() { public function getData() {
return $this->data; return $this->data;
} }
// returns JWT token in Authorization header or throw an exception
public function getJwtToken() {
$headers = getallheaders();
$autorization = $headers['Authorization'];
$arr = explode(" ", $autorization);
if(count($arr)<2)
throw new Exception("Missing JWT token");
$jwt_token = $arr[1];
return $jwt_token;
}
......
...@@ -31,6 +31,11 @@ class Response { ...@@ -31,6 +31,11 @@ class Response {
{ {
return new Response(400,$message); return new Response(400,$message);
} }
public static function unauthorizedResponse($message = "")
{
return new Response(401,$message);
}
public static function interceptEchos() { public static function interceptEchos() {
ob_start(); ob_start();
......
...@@ -8,6 +8,9 @@ define('DB_PASSWORD',''); ...@@ -8,6 +8,9 @@ define('DB_PASSWORD','');
// define('__DEBUG', false); // define('__DEBUG', false);
define('__DEBUG', true); define('__DEBUG', true);
define( 'JWT_BACKEND_KEY', '6d8HbcZndVGNAbo4Ih1TGaKcuA1y2BKs-I5CmP' );
define( 'JWT_ISSUER', $_SERVER['HTTP_HOST'] . $_SERVER['CONTEXT_PREFIX']);
// ================================================================================ // ================================================================================
// Debug utilities // Debug utilities
......
<?php
include_once __ROOT_DIR . '/libs/php-jwt/src/BeforeValidException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/ExpiredException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/SignatureInvalidException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/JWT.php';
use \Firebase\JWT\JWT;
class LoginController extends Controller {
public function __construct($name, $request) {
parent::__construct($name, $request);
}
public function processRequest() {
if($this->request->getHttpMethod() !== 'POST')
return Response::errorResponse('{ "message" : "Unsupported endpoint" }' );
$json = $this->request->getData();
if(!isset($json['login']) || !isset($json['login'])) {
$r = new Response(422,"login and pwd fields are mandatory");
$r->send();
}
$user = User::tryLogin($json['login']);
if(empty($user) || !hash_equals($json['pwd'],$user->password())) {
$r = new Response(422,"wrong credentials");
$r->send();
}
// generate json web token
$issued_at = time();
$expiration_time = $issued_at + (60 * 60); // valid for 1 hour
$token = array(
"iat" => $issued_at,
"exp" => $expiration_time,
"iss" => JWT_ISSUER,
"data" => array(
"id" => $user->id(),
"firstname" => $user->firstname(),
"lastname" => $user->lastname(),
"email" => $user->email()
)
);
$jwt = JWT::encode( $token, JWT_BACKEND_KEY );
$jsonResult = json_encode(
array(
"jwt_token" => $jwt
)
);
return Response::okResponse($jsonResult);
}
}
\ No newline at end of file
<?php <?php
include_once __ROOT_DIR . '/libs/php-jwt/src/BeforeValidException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/ExpiredException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/SignatureInvalidException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/JWT.php';
use \Firebase\JWT\JWT;
class UserController extends Controller { class UserController extends Controller {
public function __construct($name, $request) { public function __construct($name, $request) {
...@@ -20,8 +24,8 @@ class UserController extends Controller { ...@@ -20,8 +24,8 @@ class UserController extends Controller {
return $this->getAllUsers(); return $this->getAllUsers();
break; break;
case 'PUT': case 'PUT':
if ($this->request->getUriParams()) return $this->updateUser($this->request->getData());
return $this->updateUser($this->request->getUriParams()[0],$this->request->getData());
break; break;
} }
return Response::errorResponse("unsupported parameters or method in users"); return Response::errorResponse("unsupported parameters or method in users");
...@@ -41,32 +45,28 @@ class UserController extends Controller { ...@@ -41,32 +45,28 @@ class UserController extends Controller {
$response = Response::okResponse(json_encode($user)); $response = Response::okResponse(json_encode($user));
return $response; return $response;
} }
protected function updateUser($id, $data){ protected function updateUser($array){
$sets=[]; try {
if(isset($data['login'])){ $jwt_token = $this->request->getJwtToken();
$sets[] = ['USER_LOGIN',$data['login']]; // echo "jwt = $jwt_token";
} $decodedJWT = JWT::decode($jwt_token, JWT_BACKEND_KEY, array('HS256'));
if(isset($data['email'])){
$sets[] = ['USER_EMAIL',$data['email']]; if($decodedJWT->data->id != $array['id']){
} throw new Exception("You don't have access to this account.", 1);
if(isset($data['role'])){ }
$sets[] = ['USER_ROLE',$data['role']];
} User::updateUser($array);
if(isset($data['pwd'])){
$sets[] = ['USER_PWD',$data['pwd']]; } catch (Exception $e){
} header('WWW-Authenticate: Bearer realm="'.JWT_ISSUER.'"');
if(isset($data['name'])){
$sets[] = ['USER_NAME',$data['name']]; $jsonResult = json_encode(array(
} "message" => "Access denied.",
if(isset($data['surname'])){ "error" => $e->getMessage()
$sets[] = ['USER_SURNAME',$data['surname']]; ));
} return Response::unauthorizedResponse($jsonResult);
//$sets = implode(', ', $sets); }
$success = true; $response = Response::okResponse('User succesfully updated !');
foreach ($sets as $set ) { return $response;
$success &= User::update($id, $set);
}
$response = $success?Response::okResponse("Updated"):Response::errorResponse("failed");
return $response;
} }
} }
\ No newline at end of file
<?php
include_once __ROOT_DIR . '/libs/php-jwt/src/BeforeValidException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/ExpiredException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/SignatureInvalidException.php';
include_once __ROOT_DIR . '/libs/php-jwt/src/JWT.php';
use \Firebase\JWT\JWT;
class ValidateTokenController extends Controller {
public function __construct($name, $request) {
parent::__construct($name, $request);
}
public function processRequest() {
try {
$jwt_token = $this->request->getJwtToken();
// echo "jwt = $jwt_token";
$decodedJWT = JWT::decode($jwt_token, JWT_BACKEND_KEY, array('HS256'));
$jsonResult = json_encode(array(
"message" => "Access granted.",
"data" => $decodedJWT
));
} catch (Exception $e){
header('WWW-Authenticate: Bearer realm="'.JWT_ISSUER.'"');
$jsonResult = json_encode(array(
"message" => "Access denied.",
"error" => $e->getMessage()
));
return Response::unauthorizedResponse($jsonResult);
}
$response = Response::okResponse($jsonResult);
return $response;
}
}
\ No newline at end of file
...@@ -17,15 +17,30 @@ class User extends Model { ...@@ -17,15 +17,30 @@ class User extends Model {
return $stm->fetchAll(); return $stm->fetchAll();
} }
public static function update($id, $set) { public static function updateUser($array) {
$stm = parent::exec('USER_UPDATE', ['id' => $id, 'set_field' => $set[0], 'set_value' => $set[1]]); $stm = parent::exec('USER_UPDATE', $array);
try {
return true;
} catch (\Throwable $th) {
die("dommage, fromage");
}
} }
public static function tryLogin($login){
$stm = parent::exec('USER_GET_WITH_LOGIN', ['login' => $login]);
return $stm->fetchAll(PDO::FETCH_CLASS, 'User')[0];
}
public function password(){
return trim($this->USER_PWD);
}
public function id(){
return trim($this->USER_ID);
}
public function firstname(){
return trim($this->USER_NAME);
}
public function lastname(){
return trim($this->USER_SURNAME);
}
public function email(){
return trim($this->USER_EMAIL);
}
} }
\ No newline at end of file
...@@ -16,4 +16,4 @@ User::addSqlQuery('USER_CONNECT', ...@@ -16,4 +16,4 @@ User::addSqlQuery('USER_CONNECT',
'SELECT * FROM USER WHERE USER_LOGIN=:login and USER_PWD=:password'); 'SELECT * FROM USER WHERE USER_LOGIN=:login and USER_PWD=:password');
User::addSqlQuery('USER_UPDATE', User::addSqlQuery('USER_UPDATE',
'UPDATE `USER` SET :set_field = :set_value WHERE `USER_ID` = :id'); 'UPDATE USER SET USER_EMAIL = :email WHERE USER_ID = :id');
\ No newline at end of file \ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment