Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ volumes/
*.crt
*.key
*.pem
.jwks
5 changes: 5 additions & 0 deletions front_end/openVRE/apache/server.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
DocumentRoot /var/www/html/openVRE/public/
DirectoryIndex index.php

<Directory "/var/www/html/openVRE/public/api">
AllowOverride All
Require all granted
</Directory>

RewriteEngine On
RewriteRule ^/interactive-tool/([^/]+)/?(.*) http://$1:8090/$2 [P,L]

Expand Down
80 changes: 41 additions & 39 deletions front_end/openVRE/composer.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
{
"require": {
"auth0/auth0-php": "^5.0",
"cache/mongodb-adapter": "^1.1",
"jenssegers/mongodb": "^3.8",
"justinrainbow/json-schema": "^5.2",
"league/oauth2-google": "^2.0",
"mongodb/mongodb": "^1.11",
"phpseclib/phpseclib": "~3.0",
"swaggest/json-schema": "^0.12.34",
"guzzlehttp/guzzle": "*",
"ext-openssl" : "*",
"slim/slim": "4.*",
"slim/extras": "*",
"slim/http": "^1.3.0",
"slim/psr7": "^1.6.0",
"monolog/monolog": "^2.5",
"chadicus/slim-oauth2": "^3.1",
"zircote/swagger-php": "^2.0",
"squizlabs/php_codesniffer": "^3.5"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"App\\Controllers\\": "app/controllers",
"App\\Models\\": "app/models",
"App\\Middleware\\": "app/Middleware",
"App\\Handlers\\": "app/Handlers"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests"
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
"require": {
"ext-openssl": "*",
"auth0/auth0-php": "^8.0",
"chadicus/slim-oauth2": "^3.1",
"firebase/php-jwt": "^6.11",
"guzzlehttp/guzzle": "*",
"justinrainbow/json-schema": "^5.2",
"league/oauth2-google": "^2.0",
"mongodb/mongodb": "^2.1",
"monolog/monolog": "^2.5",
"phpseclib/phpseclib": "~3.0",
"slim/extras": "*",
"slim/http": "^1.3.0",
"slim/psr7": "^1.6.0",
"slim/slim": "4.*",
"squizlabs/php_codesniffer": "^3.5",
"swaggest/json-schema": "^0.12.34",
"zircote/swagger-php": "^2.0"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"App\\Controllers\\": "app/controllers",
"App\\Models\\": "app/models",
"App\\Middleware\\": "app/Middleware",
"App\\Handlers\\": "app/Handlers"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests"
}
},
"config": {
"sort-packages": true,
"allow-plugins": {
"php-http/discovery": true
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
3 changes: 2 additions & 1 deletion front_end/openVRE/public/api/.htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ RewriteEngine On
RewriteCond %{REQUEST_URI} ^/api
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
RewriteRule ^(.*)$ index.php [QSA,L]
CGIPassAuth On # https://serverfault.com/questions/1094686/rewriterule-e-http-authorizationhttpauthorization-what-does-it-mean#1094693
194 changes: 161 additions & 33 deletions front_end/openVRE/public/api/index.php
Original file line number Diff line number Diff line change
@@ -1,81 +1,209 @@
<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

use Slim\Factory\AppFactory;

require __DIR__ ."/../../config/bootstrap.php";
use Firebase\JWT\JWK;
use Firebase\JWT\JWT;

require __DIR__ . "/../../config/bootstrap.php";
require __DIR__ . "/launchTool.php";



$app = AppFactory::create();
$app->setBasePath("/api");
$app->setBasePath("/api/v1");
$app->addErrorMiddleware(true, true, true);


function getBearerToken($authHeader)
{
if (empty($authHeader)) {
throw new Exception('Authorization header not found');
}

$matchedBearer = preg_match('/^Bearer\s(\S+)$/', $authHeader, $bearerText);
if ($matchedBearer === 0) {
throw new Exception('Bearer authorization header not found');
}

if ($matchedBearer === false) {
throw new Exception('Error parsing authorization header');
}

return $bearerText[1];
}


function validateToken(string $token)
{
$jwksFilePath = '.jwks'; // Obtained from JWKS Endpoint of auth server
try {
$jwks = json_decode(file_get_contents($jwksFilePath), true);
$parsedKeySet = JWK::parseKeySet($jwks);
return JWT::decode($token, $parsedKeySet);
} catch (Exception $e) {
throw new Exception("Invalid token: " . $e->getMessage());
}
}


function checkAuthorizationToken($request, $response)
{
try {
$token = getBearerToken($request->getHeaderLine('Authorization'));
} catch (Exception $e) {
$response
->getBody()
->write(json_encode(['error' => $e->getMessage()]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(401);
}

try {
validateToken($token);
} catch (Exception $e) {
$response
->getBody()
->write(json_encode(['error' => 'Forbidden: ' . $e->getMessage()]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(403);
}

return $response;
}


$app->get('/', function (Request $request, Response $response, $args) {
$response->getBody()->write("Welcome to the OpenVRE API!\n");
return $response;
});


$app->get('/tools/', function (Request $request, Response $response, $args) {
if(!checkLoggedIn()){
return $response->withStatus(401);
$app->get('/tools', function (Request $request, Response $response, $args) {
$response = checkAuthorizationToken($request, $response);
if ($response->getStatusCode() !== 200) {
return $response;
}

$tools = $GLOBALS['toolsCol']->find();
$payload = json_encode(iterator_to_array($tools));
$response->getBody()->write($payload);
return $response
->withHeader('Content-Type', 'application/json')
->withStatus(200);

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(200);
});


$app->post('/jobs/', function (Request $request, Response $response, $args) {
$queryParams = $request->getQueryParams();
if ($queryParams['tool'] != "mock_tool") {
$response->getBody()->write(json_encode(["Error" => ["You should provide a valid tool\n"]]));
return $response
->withHeader('Content-Type', 'application/json')
->withStatus(400);
$app->get('/tools/{id}', function (Request $request, Response $response, $args) {
$response = checkAuthorizationToken($request, $response);
if ($response->getStatusCode() !== 200) {
return $response;
}

if (!filter_var($queryParams['email'], FILTER_VALIDATE_EMAIL)) {
$response->getBody()->write(json_encode(["Error" => ["You should provide a valid email\n"]]));
$options = array('typemap' => ['root' => 'array', 'document' => 'array']);
$tool = $GLOBALS['toolsCol']->findOne(array('_id' => $args['id']), $options);
if (empty($tool)) {
$response->getBody()->write(json_encode(["Error" => "Tool not found"]));
return $response
->withHeader('Content-Type', 'application/json')
->withStatus(400);
->withHeader('Content-Type', 'application/json')
->withStatus(404);
}

$payload = json_encode($tool);
$response->getBody()->write($payload);

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(200);
});


$app->post('/jobs', function (Request $request, Response $response, $args) {
try {
$toolJson = launchTool($queryParams['tool'], $queryParams['email'], $queryParams['project'], $queryParams['input_files']);
} catch (MongoDB\Exception\Exception | MongoDB\Driver\Exception\Exception $e) {
$response->getBody()->write(json_encode(["Error" => "Error connecting to database: " . $e->getMessage()]));
$token = getBearerToken($request->getHeaderLine('Authorization'));
} catch (Exception $e) {
$response
->getBody()
->write(json_encode(['error' => $e->getMessage()]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(500);
->withHeader('Content-Type', 'application/json')
->withStatus(401);
}

try {
$decodedToken = validateToken($token);
$userEmail = $decodedToken->email;
} catch (Exception $e) {
$response->getBody()->write(json_encode(["Error" => $e->getMessage()]));
$response
->getBody()
->write(json_encode(['error' => 'Forbidden: ' . $e->getMessage()]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(403);
}

$queryParams = $request->getQueryParams();
if (empty($queryParams['tool'])) {
$response->getBody()->write(json_encode(["Error" => "Missing tool id"]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(400);
}

if (empty($queryParams['project'])) {
$response->getBody()->write(json_encode(["Error" => "Missing project id"]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(500);
->withHeader('Content-Type', 'application/json')
->withStatus(400);
}

if ($_SESSION['errorData'] != null) {
$response->getBody()->write(json_encode(["Error" => $_SESSION['errorData']['Error']])); // Not returning warnings or other type of error data
$parsedBody = $request->getParsedBody();

if (empty($parsedBody['input_files'])) {
$response->getBody()->write(json_encode(["Error" => "Missing input files"]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(400);
}

try {
$toolJson = launchTool($queryParams['tool'], $userEmail, $queryParams['project'], $parsedBody['input_files']);
} catch (Exception $e) {
$response->getBody()->write(json_encode(["Error" => "Error connecting to database: " . $e->getMessage()]));

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(500);
}

if ($_SESSION['errorData']['Error'] != null) {
$response->getBody()->write(json_encode(["Error" => $_SESSION['errorData']['Error']]));
$_SESSION['errorData']['Error'] = null; // Clear the error data from the session to avoid concatenation on futher requests

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(500);
->withHeader('Content-Type', 'application/json')
->withStatus(500);
}

$payload = json_encode($toolJson);
$response->getBody()->write($payload);

return $response
->withHeader('Content-Type', 'application/json')
->withStatus(200);
->withHeader('Content-Type', 'application/json')
->withStatus(200);
});


Expand Down
Loading