Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
Fix to the WOPI server and HTTPS for the uploader
Browse files Browse the repository at this point in the history
  • Loading branch information
ghecquet committed Sep 21, 2016
1 parent 00c1338 commit 4cbb836
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 101 deletions.
20 changes: 20 additions & 0 deletions core/src/core/src/pydio/Core/Exception/RouteNotFoundException.php
@@ -0,0 +1,20 @@
<?php
/**
* Created by PhpStorm.
* User: ghecquet
* Date: 21/09/16
* Time: 14:01
*/

namespace Pydio\Core\Exception;


class RouteNotFoundException extends PydioException
{
public function __construct()
{
parent::__construct("Could not find route", null);

$this->code = 404;
}
}
2 changes: 1 addition & 1 deletion core/src/core/src/pydio/Core/Http/Base.php
Expand Up @@ -41,7 +41,7 @@ public static function handleRoute($base, $route, $additionalAttributes = []){
if ($route === "/api") {
$server = new Rest\RestApiServer($base.$route, $additionalAttributes);
} else if ($route == "/wopi") {
$server = new Wopi\RestWopiServer($base.$route, $additionalAttributes);
$server = new Wopi\Server($base.$route, $additionalAttributes);
} else if ($route === "/user") {
$_GET["get_action"] = "user_access_point";
$_GET["key"] = $additionalAttributes["key"];
Expand Down
Expand Up @@ -69,6 +69,7 @@ public function handleRequest(ServerRequestInterface $request, ResponseInterface
if(headers_sent()){
return;
}

$this->emitResponse($request, $response);
}

Expand Down
4 changes: 3 additions & 1 deletion core/src/core/src/pydio/Core/Http/Server.php
Expand Up @@ -239,7 +239,9 @@ public function catchError($code, $message, $fichier, $ligne, $context)
$req = $this->getRequest();
$resp = new Response();
$x = new SerializableResponseStream();
$resp = $resp->withBody($x);
$resp = $resp
->withStatus($code)
->withBody($x);
$x->addChunk(new UserMessage($message, LOG_LEVEL_ERROR));
$this->topMiddleware->emitResponse($req, $resp);

Expand Down
111 changes: 111 additions & 0 deletions core/src/core/src/pydio/Core/Http/Wopi/AuthFrontend.php
@@ -0,0 +1,111 @@
<?php
/*
* Copyright 2007-2013 Charles du Jeu - Abstrium SAS <team (at) pyd.io>
* This file is part of Pydio.
*
* Pydio is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pydio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Pydio. If not, see <http://www.gnu.org/licenses/>.
*
* The latest code can be found at <http://pyd.io/>.
*/
namespace Pydio\Core\Http\Wopi;

use JWT;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Pydio\Core\Services\ApiKeysService;
use Pydio\Core\Services\AuthService;
use Pydio\Auth\Frontend\Core\AbstractAuthFrontend;
use Pydio\Conf\Sql\SqlConfDriver;

defined('AJXP_EXEC') or die('Access not allowed');


/**
* Class Pydio\Core\Http\Wopi\WopiJWTAuthFrontend;
*/
class AuthFrontend extends AbstractAuthFrontend
{
const NOT_FOUND = "";

/**
* @var SqlConfDriver $storage
*/
var $storage;

/**
* @param $httpVars
* @param $varName
* @return string
*/
function detectVar(&$httpVars, $varName)
{
if (isSet($httpVars[$varName])) return $httpVars[$varName];
if (isSet($_SERVER["HTTP_PYDIO_" . strtoupper($varName)])) return $_SERVER["HTTP_" . strtoupper($varName)];
return "";
}

/**
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param bool $isLast
* @return bool
*/
function tryToLogUser(ServerRequestInterface &$request, ResponseInterface &$response, $isLast = false) {
// This plugin is depending on other authfront having found the current user
$currentUser = AuthService::getLoggedUser();
if (!isset($currentUser)) {
return false;
}

$httpVars = $request->getParsedBody();
$jwt = $this->detectVar($httpVars, "access_token");
if (empty($jwt)) {
return false;
}

// We have an access token - decode
$payload = JWT::decode($jwt);

if (!isset($payload->token) || !isset($payload->task)) {
return false;
}

// We have a token - retrieve private signature
$token = $payload->token;
$task = $payload->task;

$key = ApiKeysService::findPairForAdminTask($task, $currentUser->getId());
$signature = self::NOT_FOUND;

if ($key["t"] !== $token) {
return false;
}

$signature = $key["p"];

if ($signature == self::NOT_FOUND) {
return false;
}

// We have a signature - verify the payload
try {
JWT::decode($jwt, $signature, ['HS256']);
} catch (\Exception $e) {
return false;
}

// We're through
return true;
}
}
Expand Up @@ -45,7 +45,7 @@
* Authentication middleware used in Rest context
* @package Pydio\Core\Http\Rest
*/
class RestWopiAuthMiddleware
class AuthMiddleware
{

/**
Expand All @@ -64,6 +64,14 @@ public static function handleRequest(ServerRequestInterface $requestInterface, R
if($response != null){
return $response;
}

$response = (new AuthFrontend("jwt-auth-frontend", ""))->tryToLogUser($requestInterface, $responseInterface);
if(!$response != null) {
$responseInterface = $responseInterface->withStatus(401);
$responseInterface->getBody()->write('You are not authorized to access this API.');
return $responseInterface;
}

/** @var ContextInterface $ctx */
$ctx = $requestInterface->getAttribute("ctx");

Expand Down
Expand Up @@ -24,22 +24,45 @@
use \Psr\Http\Message\ResponseInterface;
use Pydio\Access\Core\Model\AJXP_Node;
use Pydio\Access\Core\Model\NodesList;

use Pydio\Core\Exception\PydioException;
use Pydio\Core\Exception\RouteNotFoundException;
use Pydio\Core\Http\Message\Message;
use Pydio\Core\Http\Middleware\SapiMiddleware;
use Pydio\Core\Http\Response\SerializableResponseStream;
use Zend\Diactoros\Response\EmptyResponse;
use Zend\Diactoros\Response\SapiEmitter;

defined('AJXP_EXEC') or die('Access not allowed');

/**
* Class WopiMiddleware
* Main Middleware for Wopi requests
* @package Pydio\Core\Http\Middleware
* Class RestWopiMiddleware
* Specific middleware to handle Wopi actions
* @package Pydio\Core\Http\Wopi
*/
class WopiMiddleware extends SapiMiddleware
class Middleware extends SapiMiddleware
{
protected $base;

/**
* RestWopiMiddleware constructor.
* @param $base
*/
public function __construct($base)
{
$this->base = $base;
}

/**
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @throws PydioException
*/
protected function parseRequestRouteAndParams(ServerRequestInterface &$request, ResponseInterface &$response){

$router = new Router($this->base);
if(!$router->route($request, $response)) {
throw new RouteNotFoundException();
}
}

/**
* Output the response to the browser, if no headers were already sent.
Expand All @@ -50,32 +73,39 @@ class WopiMiddleware extends SapiMiddleware
public function emitResponse(ServerRequestInterface $request, ResponseInterface $response) {

if($response !== false && $response->getBody() && $response->getBody() instanceof SerializableResponseStream){

/**
* @var SerializableResponseStream $body;
*/
$status = &$response->getStatusCode();

$body = &$response->getBody();
// Modifying the results
if ($status == 200) {
$body = &$response->getBody();

/** @var NodesList $originalData */
$originalData = $body->getChunks()[0];

/** @var AJXP_Node $node */
$node = $originalData->getChildren()[0];

// We modify the result to have the correct format required by the api
$x = new SerializableResponseStream();
$meta = $node->getNodeInfoMeta();
$userId = $node->getUser()->getId();
$data = [
"BaseFileName" => $node->getLabel(),
"OwnerId" => $userId,
"Size" => $meta["bytesize"],
"UserId" => $userId,
"Version" => "" . $meta["ajxp_modiftime"]
];

$x->addChunk(new Message($data));
$response = $response->withBody($x);

}

/** @var NodesList $originalData */
$originalData = $body->getChunks()[0];

/** @var AJXP_Node $node */
$node = $originalData->getChildren()[0];

// We modify the result to have the correct format required by the api
$x = new SerializableResponseStream();
$meta = $node->getNodeInfoMeta();
$userId = $node->getUser()->getId();
$data = [
"BaseFileName" => $node->getLabel(),
"OwnerId" => $userId,
"Size" => $meta["bytesize"],
"UserId" => $userId,
"Version" => "" . $meta["ajxp_modiftime"]
];

$x->addChunk(new Message($data));
$response = $response->withBody($x);
$body = &$response->getBody();

$params = $request->getParsedBody();
Expand All @@ -91,9 +121,7 @@ public function emitResponse(ServerRequestInterface $request, ResponseInterface
} else {
$body->setSerializer(SerializableResponseStream::SERIALIZER_TYPE_JSON);
$response = $response->withHeader("Content-type", "application/json; charset=UTF-8");

}

}

if($response !== false && ($response->getBody()->getSize() || $response instanceof EmptyResponse) || $response->getStatusCode() != 200) {
Expand Down
60 changes: 0 additions & 60 deletions core/src/core/src/pydio/Core/Http/Wopi/RestWopiMiddleware.php

This file was deleted.

Expand Up @@ -32,7 +32,7 @@
* Simple router for /wopi/ endpoints
* @package Pydio\Core\Http\Wopi
*/
class WopiRouter
class Router
{
/**
* @var array
Expand Down Expand Up @@ -116,7 +116,7 @@ public function route(ServerRequestInterface &$request, ResponseInterface &$resp

switch ($routeInfo[0]) {
case Dispatcher::NOT_FOUND:
//$response = $response->withStatus(404);
$response = $response->withStatus(404);
break;
case Dispatcher::METHOD_NOT_ALLOWED:
//$allowedMethods = $routeInfo[1];
Expand Down

0 comments on commit 4cbb836

Please sign in to comment.