<?php
/**
 * While request the api the api must have a Token which will be validated each
 * and every time in this method. if the token will be validated then the server
 * responses with a valid response or else, an error message will be thrown
 *
 * __invoke(): The __invoke() method gets called when the object is called as a
 * function. When you declare it, you say which arguments it should expect
 *
 * PHP version 5.6
 *
 * @category  Middleware
 * @package   Middleware
 * @author    Tanmaya Patra <tanmayap@riaxe.com>
 * @copyright 2019-2020 Riaxe Systems
 * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
 * @link      http://inkxe-v10.inkxe.io/xetool/admin
 */
namespace App\Middlewares;

use App\Components\Controllers\Component as ParentController;
use \Firebase\JWT\JWT;

/**
 * Validate JWT Token Class
 *
 * @category Middleware
 * @package  Middleware
 * @author   Tanmaya Patra <tanmayap@riaxe.com>
 * @license  http://www.gnu.org/copyleft/gpl.html GNU General Public License
 * @link     http://inkxe-v10.inkxe.io/xetool/admin
 */
class ValidateJWTToken extends ParentController
{
    /**
     * Check JWT Token
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $next     IF all goes good, then the code moved to teh next step
     *
     * @author tanmayap@riaxe.com
     * @date   07 Aug 2019
     * @return Json
     */
    public function __invoke($request, $response, $next)
    {
        $checkArr =  get_app_settings('jwtRoutesCheck');
        $serverStatusCode = AUTH_ERROR;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Authentication Token', 'token_mismatch'),
        ];
        $doAllowJWT = get_app_settings('do_load_jwt');
        $getJWTSecret = get_app_settings('jwt_secret');
        $headers = server_request_headers();
        // Easily turn on/off JWT from config
        if ($doAllowJWT === false) {
            return $next($request, $response);
        }

        $getToken = "";
        if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
            $secureUrl = "https://";
        } else {
            $secureUrl = "http://";
        }
        $secureUrl."$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        foreach ($checkArr as $check) {
            if (!empty($_REQUEST['_token'])) {
                 $getToken = "Bearer " . $_REQUEST['_token'];
            } else if(!empty($headers['TOKEN'])){
                $getToken = $headers['TOKEN'];
            }
        }

        if (!empty($getToken) && $doAllowJWT === true) {
            try
            {
                $tokenWithBearer = explode(" ", $getToken);
                $token = (isset($tokenWithBearer[1]) && $tokenWithBearer[1] != "") ? $tokenWithBearer[1] : null;
                $jwtObj = new JWT();
                $jwtObj::$leeway = 5000;
                $decodedToken =  $jwtObj->decode($token, $getJWTSecret, array('HS256'));
                $currTimestamp = time();
                if ($decodedToken->exp < $currTimestamp) {
                    throw new \Exception('Token expired');
                }
                return $next($request, $response);
            } catch (\Exception $e) {
                $serverStatusCode = AUTH_ERROR;
                if (show_exception() === true) {
                    $jsonResponse += [
                        'exception' => $e->getMessage()
                    ];
                }
                create_log('activity', 'warning', [
                    'message' => 'JWT Token does not match',
                    'extra' => $jsonResponse
                ]);
            }
        }
        return response(
            $response, ['data' => $jsonResponse, 'status' => $serverStatusCode]
        );
    }
}
