Merge pull request #1360 from bburnichon/feature/controller-as-service

controller as service
This commit is contained in:
Benoît Burnichon
2015-05-07 16:09:40 +02:00
62 changed files with 2989 additions and 2383 deletions

View File

@@ -12,8 +12,6 @@
namespace Alchemy\Phrasea;
use Alchemy\Geonames\GeonamesServiceProvider;
use Alchemy\Phrasea\ControllerProvider\Admin\TaskManager;
use Alchemy\Phrasea\ControllerProvider\Client\Root as ClientRoot;
use Alchemy\Phrasea\ControllerProvider\Prod\BasketController;
use Alchemy\Phrasea\ControllerProvider\Prod\Bridge;
use Alchemy\Phrasea\ControllerProvider\Prod\DoDownload;
@@ -314,6 +312,7 @@ class Application extends SilexApplication
'Alchemy\Phrasea\ControllerProvider\Admin\Subdefs' => [],
'Alchemy\Phrasea\ControllerProvider\Admin\TaskManager' => [],
'Alchemy\Phrasea\ControllerProvider\Admin\Users' => [],
'Alchemy\Phrasea\ControllerProvider\Client\Root' => [],
'Alchemy\Phrasea\ControllerProvider\Datafiles' => [],
'Alchemy\Phrasea\ControllerProvider\Lightbox' => [],
'Alchemy\Phrasea\ControllerProvider\Minifier' => [],
@@ -623,8 +622,6 @@ class Application extends SilexApplication
$this->mount('/login/', new Login());
$this->mount('/developers/', new Developers());
$this->mount('/client/', new ClientRoot());
$this->mount('/prod/query/', new Query());
$this->mount('/prod/order/', new Order());
$this->mount('/prod/baskets', new BasketController());
@@ -677,6 +674,7 @@ class Application extends SilexApplication
'/admin/subdefs' => 'Alchemy\Phrasea\ControllerProvider\Admin\Subdefs',
'/admin/task-manager' => 'Alchemy\Phrasea\ControllerProvider\Admin\TaskManager',
'/admin/users' => 'Alchemy\Phrasea\ControllerProvider\Admin\Users',
'/client/' => 'Alchemy\Phrasea\ControllerProvider\Client\Root',
'/datafiles' => 'Alchemy\Phrasea\ControllerProvider\Datafiles',
'/include/minify' => 'Alchemy\Phrasea\ControllerProvider\Minifier',
'/lightbox' => 'Alchemy\Phrasea\ControllerProvider\Lightbox',

View File

@@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Api\Result;
use Alchemy\Phrasea\ControllerProvider\Api\Oauth2;
use Alchemy\Phrasea\ControllerProvider\Api\OAuth2;
use Alchemy\Phrasea\ControllerProvider\Api\V1;
use Alchemy\Phrasea\ControllerProvider\Datafiles;
use Alchemy\Phrasea\ControllerProvider\Minifier;
@@ -32,6 +32,9 @@ use Symfony\Component\HttpFoundation\Response;
return call_user_func(function ($environment = PhraseaApplication::ENV_PROD) {
$app = new PhraseaApplication($environment);
$app->register(new OAuth2());
$app->register(new V1());
$app->loadPlugins();
$app['exception_handler'] = $app->share(function ($app) {
@@ -114,7 +117,7 @@ return call_user_func(function ($environment = PhraseaApplication::ENV_PROD) {
])->createResponse();
});
$app->mount('/api/oauthv2', new Oauth2());
$app->mount('/api/oauthv2', new OAuth2());
$app->mount('/datafiles/', new Datafiles());
$app->mount('/api/v1', new V1());
$app->mount('/permalink/', new Permalink());

View File

@@ -24,8 +24,8 @@ class Response
/**
* Constructor
*
* @param boolean $ok True if the response is OK
* @param Checker $checker The checker attachedto the response
* @param boolean $ok True if the response is OK
* @param CheckerInterface $checker The checker attachedto the response
*/
public function __construct($ok, CheckerInterface $checker)
{

View File

@@ -97,11 +97,11 @@ class Manager
*
* @param LazaretSession $session The current Lazaret Session
* @param File $file A File package object
* @param type $callable A callback to execute after process
* @param callable $callable A callback to execute after process
* (arguments are $element (LazaretFile or \record_adapter),
* $visa (Visa)
* and $code (self::RECORD_CREATED or self::LAZARET_CREATED))
* @param type $forceBehavior Force a behavior, one of the self::FORCE_* constant
* @param bool $forceBehavior Force a behavior, one of the self::FORCE_* constant
* @return int One of the self::RECORD_CREATED or self::LAZARET_CREATED constants
*/
public function process(LazaretSession $session, File $file, $callable = null, $forceBehavior = null, $nosubdef = false)

View File

@@ -10,9 +10,6 @@
namespace Alchemy\Phrasea\Controller\Admin;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Authentication\ACLProvider;
use Alchemy\Phrasea\Authentication\Authenticator;
use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Core\Response\CSVFileResponse;
use Alchemy\Phrasea\Helper\User as UserHelper;

View File

@@ -0,0 +1,206 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Controller\Api;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Authentication\Context;
use Alchemy\Phrasea\Authentication\Exception\AccountLockedException;
use Alchemy\Phrasea\Authentication\Exception\RequireCaptchaException;
use Alchemy\Phrasea\Authentication\Phrasea\PasswordAuthenticationInterface;
use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Core\Event\PostAuthenticate;
use Alchemy\Phrasea\Core\Event\PreAuthenticate;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Model\Manipulator\ApiAccountManipulator;
use Alchemy\Phrasea\Model\Repositories\ApiApplicationRepository;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class OAuth2Controller extends Controller
{
/** @var \API_OAuth2_Adapter */
private $oAuth2Adapter;
/** @var EventDispatcherInterface */
private $dispatcher;
public function __construct(Application $app)
{
parent::__construct($app);
$this->oAuth2Adapter = $app['oauth2-server'];
$this->dispatcher = $app['dispatcher'];
}
/**
* AUTHORIZE ENDPOINT
*
* Authorization endpoint - used to obtain authorization from the
* resource owner via user-agent redirection.
* @param Request $request
* @return string|Response
*/
public function authorizeAction(Request $request)
{
$context = new Context(Context::CONTEXT_OAUTH2_NATIVE);
$this->dispatcher->dispatch(PhraseaEvents::PRE_AUTHENTICATE, new PreAuthenticate($request, $context));
//Check for auth params, send error or redirect if not valid
$params = $this->oAuth2Adapter->getAuthorizationRequestParameters($request);
$appAuthorized = false;
$error = $request->get('error', '');
/** @var ApiApplicationRepository $appRepository */
$appRepository = $this->app['repo.api-applications'];
if (null === $client = $appRepository->findByClientId($params['client_id'])) {
throw new NotFoundHttpException(sprintf('Application with client id %s could not be found', $params['client_id']));
}
$this->oAuth2Adapter->setClient($client);
$actionAccept = $request->get("action_accept");
$actionLogin = $request->get("action_login");
$template = "api/auth/end_user_authorization.html.twig";
$custom_template = sprintf(
"%s/config/templates/web/api/auth/end_user_authorization/%s.html.twig"
, $this->app['root.path']
, $client->getId()
);
if (file_exists($custom_template)) {
$template = sprintf(
'api/auth/end_user_authorization/%s.html.twig'
, $client->getId()
);
}
if (!$this->getAuthenticator()->isAuthenticated()) {
if ($actionLogin !== null) {
try {
/** @var PasswordAuthenticationInterface $authentication */
$authentication = $this->app['auth.native'];
if (null === $usrId = $authentication->getUsrId($request->get("login"), $request->get("password"), $request)) {
$this->getSession()->getFlashBag()
->set('error', $this->app->trans('login::erreur: Erreur d\'authentification'));
return $this->app->redirectPath('oauth2_authorize', array_merge(array('error' => 'login'), $params));
}
} catch (RequireCaptchaException $e) {
return $this->app->redirectPath('oauth2_authorize', array_merge(array('error' => 'captcha'), $params));
} catch (AccountLockedException $e) {
return $this->app->redirectPath('oauth2_authorize', array_merge(array('error' => 'account-locked'), $params));
}
$user = $this->app['repo.users']->find($usrId);
$this->getAuthenticator()->openAccount($user);
$event = new PostAuthenticate($request, new Response(), $user, $context);
$this->dispatcher->dispatch(PhraseaEvents::POST_AUTHENTICATE, $event);
} else {
$r = new Response($this->render($template, array('error' => $error, "auth" => $this->oAuth2Adapter)));
$r->headers->set('Content-Type', 'text/html');
return $r;
}
}
//check if current client is already authorized by current user
$clients = $appRepository->findAuthorizedAppsByUser($this->getAuthenticatedUser());
foreach ($clients as $authClient) {
if ($client->getClientId() == $authClient->getClientId()) {
$appAuthorized = true;
break;
}
}
$account = $this->oAuth2Adapter->updateAccount($this->getAuthenticatedUser());
$params['account_id'] = $account->getId();
if (!$appAuthorized && $actionAccept === null) {
$params = [
"auth" => $this->oAuth2Adapter,
"error" => $error,
];
$r = new Response($this->render($template, $params));
$r->headers->set('Content-Type', 'text/html');
return $r;
} elseif (!$appAuthorized && $actionAccept !== null) {
$appAuthorized = (Boolean) $actionAccept;
if ($appAuthorized) {
$this->getApiAccountManipulator()
->authorizeAccess($account);
} else {
$this->getApiAccountManipulator()
->revokeAccess($account);
}
}
//if native app show template
if ($this->oAuth2Adapter->isNativeApp($params['redirect_uri'])) {
$params = $this->oAuth2Adapter->finishNativeClientAuthorization($appAuthorized, $params);
$r = new Response($this->render("api/auth/native_app_access_token.html.twig", $params));
$r->headers->set('Content-Type', 'text/html');
return $r;
}
$this->oAuth2Adapter->finishClientAuthorization($appAuthorized, $params);
// As OAuth2 library already outputs response content, we need to send an empty
// response to avoid breaking silex controller
return '';
}
/**
* TOKEN ENDPOINT
* Token endpoint - used to exchange an authorization grant for an access token.
* @param Request $request
* @return string
*/
public function tokenAction(Request $request)
{
if ( ! $request->isSecure()) {
throw new HttpException(400, 'This route requires the use of the https scheme', null, ['content-type' => 'application/json']);
}
$this->oAuth2Adapter->grantAccessToken($request);
ob_flush();
flush();
// As OAuth2 library already outputs response content, we need to send an empty
// response to avoid breaking silex controller
return '';
}
/**
* @return Session
*/
public function getSession()
{
return $this->app['session'];
}
/**
* @return ApiAccountManipulator
*/
public function getApiAccountManipulator()
{
return $this->app['manipulator.api-account'];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Controller\Client;
use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Security\Firewall;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class RootController extends Controller
{
/**
* @return Firewall
*/
private function getFirewall()
{
return $this->app['firewall'];
}
/**
* Gets client main page
*
* @param Request $request
* @return Response
*/
public function getClientAction(Request $request)
{
if (!$this->getAuthenticator()->isAuthenticated() && null !== $request->query->get('nolog')) {
return $this->app->redirectPath('login_authenticate_as_guest', ['redirect' => 'client']);
}
if (null !== $response = $this->getFirewall()->requireAuthentication()) {
return $response;
}
return $this->app->redirect($this->app->path('prod', array('client')));
}
}

View File

@@ -13,13 +13,15 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\CollectionController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class Collection implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.collection'] = $app->share(function (PhraseaApplication $app) {
@@ -33,10 +35,7 @@ class Collection implements ControllerProviderInterface, ServiceProviderInterfac
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('admin')

View File

@@ -13,13 +13,15 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\ConnectedUsersController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class ConnectedUsers implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.connected-users'] = $app->share(function (PhraseaApplication $app) {
@@ -43,10 +45,7 @@ class ConnectedUsers implements ControllerProviderInterface, ServiceProviderInte
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('Admin');

View File

@@ -13,15 +13,17 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\DataboxController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Security\Firewall;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
use Symfony\Component\HttpFoundation\Request;
class Databox implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.databox'] = $app->share(function (PhraseaApplication $app) {
@@ -35,10 +37,7 @@ class Databox implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers
->before(function (Request $request) use ($app) {

View File

@@ -13,14 +13,15 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\DataboxesController;
use Alchemy\Phrasea\Security\Firewall;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class Databoxes implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.databoxes'] = $app->share(function (PhraseaApplication $app) {
@@ -34,12 +35,8 @@ class Databoxes implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
/** @var Firewall $firewall */
$firewall = $app['firewall'];
$firewall->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$controllers->before(function () use ($firewall) {
$firewall->requireAccessToModule('admin');

View File

@@ -13,14 +13,15 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\FeedController;
use Alchemy\Phrasea\Security\Firewall;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class Feeds implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.feeds'] = $app->share(function (PhraseaApplication $app) {
@@ -34,12 +35,8 @@ class Feeds implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
/** @var Firewall $firewall */
$firewall = $app['firewall'];
$firewall->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$controllers->before(function () use ($firewall) {
$firewall

View File

@@ -13,14 +13,15 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\FieldsController;
use Alchemy\Phrasea\Security\Firewall;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class Fields implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.fields'] = $app->share(function (PhraseaApplication $app) {
@@ -34,12 +35,8 @@ class Fields implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
/** @var Firewall $firewall */
$firewall = $app['firewall'];
$firewall->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$controllers->before(function () use ($firewall) {
$firewall

View File

@@ -13,14 +13,15 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\RootController;
use Alchemy\Phrasea\Security\Firewall;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class Root implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.root'] = $app->share(function (PhraseaApplication $app) {
@@ -34,12 +35,8 @@ class Root implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
/** @var Firewall $firewall */
$firewall = $app['firewall'];
$firewall->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$controllers->before(function () use ($firewall) {
$firewall->requireAccessToModule('admin');

View File

@@ -13,15 +13,16 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Admin\SubdefsController;
use Alchemy\Phrasea\Security\Firewall;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
use Symfony\Component\HttpFoundation\Request;
class Subdefs implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.subdefs'] = $app->share(function (PhraseaApplication $app) {
@@ -35,12 +36,8 @@ class Subdefs implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
/** @var Firewall $firewall */
$firewall = $app['firewall'];
$firewall->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$controllers->before(function (Request $request) use ($firewall) {
$firewall->requireAccessToModule('admin')

View File

@@ -12,15 +12,16 @@
namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Controller\Admin\TaskManagerController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Converter\TaskConverter;
use Alchemy\Phrasea\Security\Firewall;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class TaskManager implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.task'] = $app->share(function (\Alchemy\Phrasea\Application $app) {
@@ -34,12 +35,8 @@ class TaskManager implements ControllerProviderInterface, ServiceProviderInterfa
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
/** @var Firewall $firewall */
$firewall = $app['firewall'];
$firewall->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$converter = function ($task) use ($app) {
/** @var TaskConverter $converter */

View File

@@ -12,13 +12,15 @@
namespace Alchemy\Phrasea\ControllerProvider\Admin;
use Alchemy\Phrasea\Controller\Admin\UserController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class Users implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.admin.users'] = $app->share(function () use ($app) {
@@ -32,13 +34,11 @@ class Users implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
$controllers = $this->createAuthenticatedCollection($app);
$firewall = $this->getFirewall($app);
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('admin')
$controllers->before(function () use ($firewall) {
$firewall->requireAccessToModule('admin')
->requireRight('manageusers');
});

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\ControllerProvider\Api;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Api\OAuth2Controller;
use Silex\Application;
use Silex\ControllerCollection;
use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface;
class OAuth2 implements ControllerProviderInterface, ServiceProviderInterface
{
public function register(Application $app)
{
$app['controller.oauth2'] = $app->share(function (PhraseaApplication $app) {
return new OAuth2Controller($app);
});
}
public function boot(Application $app)
{
}
public function connect(Application $app)
{
/** @var ControllerCollection $controllers */
$controllers = $app['controllers_factory'];
$controllers->match('/authorize', 'controller.oauth2:authorizeAction')
->method('GET|POST')
->bind('oauth2_authorize');
$controllers->post('/token', 'controller.oauth2:tokenAction');
return $controllers;
}
}

View File

@@ -1,178 +0,0 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\ControllerProvider\Api;
use Alchemy\Phrasea\Authentication\Context;
use Alchemy\Phrasea\Authentication\Exception\AccountLockedException;
use Alchemy\Phrasea\Authentication\Exception\RequireCaptchaException;
use Alchemy\Phrasea\Core\Event\PreAuthenticate;
use Alchemy\Phrasea\Core\Event\PostAuthenticate;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class Oauth2 implements ControllerProviderInterface
{
public function connect(Application $app)
{
$app['controller.oauth2'] = $this;
$controllers = $app['controllers_factory'];
/**
* AUTHORIZE ENDPOINT
*
* Authorization endpoint - used to obtain authorization from the
* resource owner via user-agent redirection.
*/
$authorize_func = function () use ($app) {
$request = $app['request'];
$oauth2Adapter = $app['oauth2-server'];
$context = new Context(Context::CONTEXT_OAUTH2_NATIVE);
$app['dispatcher']->dispatch(PhraseaEvents::PRE_AUTHENTICATE, new PreAuthenticate($request, $context));
//Check for auth params, send error or redirect if not valid
$params = $oauth2Adapter->getAuthorizationRequestParameters($request);
$appAuthorized = false;
$error = $request->get('error', '');
if (null === $client = $app['repo.api-applications']->findByClientId($params['client_id'])) {
throw new NotFoundHttpException(sprintf('Application with client id %s could not be found', $params['client_id']));
}
$oauth2Adapter->setClient($client);
$actionAccept = $request->get("action_accept");
$actionLogin = $request->get("action_login");
$template = "api/auth/end_user_authorization.html.twig";
$custom_template = sprintf(
"%s/config/templates/web/api/auth/end_user_authorization/%s.html.twig"
, $app['root.path']
, $client->getId()
);
if (file_exists($custom_template)) {
$template = sprintf(
'api/auth/end_user_authorization/%s.html.twig'
, $client->getId()
);
}
if (!$app['authentication']->isAuthenticated()) {
if ($actionLogin !== null) {
try {
if (null === $usrId = $app['auth.native']->getUsrId($request->get("login"), $request->get("password"), $request)) {
$app['session']->getFlashBag()->set('error', $app->trans('login::erreur: Erreur d\'authentification'));
return $app->redirectPath('oauth2_authorize', array_merge(array('error' => 'login'), $params));
}
} catch (RequireCaptchaException $e) {
return $app->redirectPath('oauth2_authorize', array_merge(array('error' => 'captcha'), $params));
} catch (AccountLockedException $e) {
return $app->redirectPath('oauth2_authorize', array_merge(array('error' => 'account-locked'), $params));
}
$user = $app['repo.users']->find($usrId);
$app['authentication']->openAccount($user);
$event = new PostAuthenticate($request, new Response(), $user, $context);
$app['dispatcher']->dispatch(PhraseaEvents::POST_AUTHENTICATE, $event);
} else {
$r = new Response($app['twig']->render($template, array('error' => $error, "auth" => $oauth2Adapter)));
$r->headers->set('Content-Type', 'text/html');
return $r;
}
}
//check if current client is already authorized by current user
$clients = $app['repo.api-applications']->findAuthorizedAppsByUser($app['authentication']->getUser());
foreach ($clients as $authClient) {
if ($client->getClientId() == $authClient->getClientId()) {
$appAuthorized = true;
break;
}
}
$account = $oauth2Adapter->updateAccount($app['authentication']->getUser());
$params['account_id'] = $account->getId();
if (!$appAuthorized && $actionAccept === null) {
$params = [
"auth" => $oauth2Adapter,
"error" => $error,
];
$r = new Response($app['twig']->render($template, $params));
$r->headers->set('Content-Type', 'text/html');
return $r;
} elseif (!$appAuthorized && $actionAccept !== null) {
$appAuthorized = (Boolean) $actionAccept;
if ($appAuthorized) {
$app['manipulator.api-account']->authorizeAccess($account);
} else {
$app['manipulator.api-account']->revokeAccess($account);
}
}
//if native app show template
if ($oauth2Adapter->isNativeApp($params['redirect_uri'])) {
$params = $oauth2Adapter->finishNativeClientAuthorization($appAuthorized, $params);
$r = new Response($app['twig']->render("api/auth/native_app_access_token.html.twig", $params));
$r->headers->set('Content-Type', 'text/html');
return $r;
}
$oauth2Adapter->finishClientAuthorization($appAuthorized, $params);
// As OAuth2 library already outputs response content, we need to send an empty
// response to avoid breaking silex controller
return '';
};
$controllers->match('/authorize', $authorize_func)
->method('GET|POST')
->bind('oauth2_authorize');
/**
* TOKEN ENDPOINT
* Token endpoint - used to exchange an authorization grant for an access token.
*/
$controllers->post('/token', function (\Silex\Application $app, Request $request) {
if ( ! $request->isSecure()) {
throw new HttpException(400, 'This route requires the use of the https scheme', null, ['content-type' => 'application/json']);
}
$app['oauth2-server']->grantAccessToken($request);
ob_flush();
flush();
// As OAuth2 library already outputs response content, we need to send an empty
// response to avoid breaking silex controller
return '';
});
return $controllers;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -11,49 +11,33 @@
namespace Alchemy\Phrasea\ControllerProvider\Client;
use Alchemy\Phrasea\Feed\Aggregate;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\Exception\SessionNotFound;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Client\RootController;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Silex\ServiceProviderInterface;
class Root implements ControllerProviderInterface
class Root implements ControllerProviderInterface, ServiceProviderInterface
{
public function register(Application $app)
{
$app['controller.client'] = $app->share(function (PhraseaApplication $app) {
return new RootController($app);
});
}
public function boot(Application $app)
{
// no-op
}
public function connect(Application $app)
{
$app['controller.client'] = $this;
$controllers = $app['controllers_factory'];
$controllers->before(function (Request $request) use ($app) {
if (!$app['authentication']->isAuthenticated() && null !== $request->query->get('nolog')) {
return $app->redirectPath('login_authenticate_as_guest', ['redirect' => 'client']);
}
if (null !== $response = $app['firewall']->requireAuthentication()) {
return $response;
}
});
$controllers->get('/', 'controller.client:getClient')
$controllers->get('/', 'controller.client:getClientAction')
->bind('get_client');
return $controllers;
}
/**
* Gets client main page
*
* @param Application $app
* @param Request $request
* @return Response
*/
public function getClient(Application $app, Request $request)
{
return $app->redirect($app->path('prod', array('client')));
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\ControllerProvider;
use Alchemy\Phrasea\Security\Firewall;
use Silex\Application;
use Silex\ControllerCollection;
trait ControllerProviderTrait
{
/**
* @param Application $app
* @return ControllerCollection
*/
protected function createAuthenticatedCollection(Application $app)
{
$controllers = $app['controllers_factory'];
$this->getFirewall($app)->addMandatoryAuthentication($controllers);
return $controllers;
}
/**
* @param Application $app
* @return ControllerCollection
*/
protected function createCollection(Application $app)
{
return $app['controllers_factory'];
}
/**
* @param Application $app
* @return Firewall
*/
protected function getFirewall(Application $app)
{
return $app['firewall'];
}
}

View File

@@ -23,6 +23,8 @@ use Symfony\Component\HttpFoundation\Request;
class Lightbox implements ControllerProviderInterface, ServiceProviderInterface
{
use ControllerProviderTrait;
public function register(Application $app)
{
$app['controller.lightbox'] = $app->share(function (PhraseaApplication $app) {
@@ -36,11 +38,12 @@ class Lightbox implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app)
{
$controllers = $app['controllers_factory'];
$controllers = $this->createCollection($app);
$controllers->before([$this, 'redirectOnLogRequests']);
$app['firewall']->addMandatoryAuthentication($controllers);
$firewall = $this->getFirewall($app);
$firewall->addMandatoryAuthentication($controllers);
$controllers
// Silex\Route::convert is not used as this should be done prior the before middleware

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\Basket as BasketEntity;
use Alchemy\Phrasea\Model\Entities\BasketElement;
use Alchemy\Phrasea\Model\Entities\ValidationData;
@@ -23,13 +24,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class BasketController implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.basket'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers
// Silex\Route::convert is not used as this should be done prior the before middleware

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\Prod\HttpException;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Helper\Record as RecordHelper;
use Silex\Application;
use Silex\ControllerProviderInterface;
@@ -20,13 +21,13 @@ use Symfony\Component\HttpFoundation\Request;
class Bridge implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['bridge.controller'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('bas_chupub');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\ExportEvent;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Silex\Application;
@@ -20,6 +21,8 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
class Download implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
*/
@@ -27,9 +30,7 @@ class Download implements ControllerProviderInterface
{
$app['controller.prod.download'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->post('/', 'controller.prod.download:checkDownload')
->bind('check_download');

View File

@@ -11,25 +11,25 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\Prod\record_adapter;
use record_adapter;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\RecordEdit;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Vocabulary\Controller as VocabularyController;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\Metadata\Tag\TfEditdate;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
class Edit implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.edit'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\ExportFailureEvent;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Silex\Application;
@@ -25,6 +26,8 @@ use Symfony\Component\HttpFoundation\Response;
class Export implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
*/
@@ -32,10 +35,7 @@ class Export implements ControllerProviderInterface
{
$app['controller.prod.export'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->post('/multi-export/', 'controller.prod.export:displayMultiExport')
->bind('export_multi_export');

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\FeedEntryEvent;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Feed\Aggregate;
@@ -27,13 +28,13 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class Feed implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.feed'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->post('/requestavailable/', function (Application $app, Request $request) {
$feeds = $app['repo.feeds']->getAllForUser(

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\LazaretFile;
use Alchemy\Phrasea\Border;
use Alchemy\Phrasea\Border\Attribute\AttributeInterface;
@@ -23,6 +24,8 @@ use Symfony\Component\Filesystem\Exception\IOException;
class Lazaret implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* Connect the ControllerCollection to the Silex Application
*
@@ -33,9 +36,7 @@ class Lazaret implements ControllerProviderInterface
{
$app['controller.prod.lazaret'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('addrecord');

View File

@@ -12,19 +12,20 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
class MoveCollection implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.move-collection'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('addrecord')

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\OrderDeliveryEvent;
use Alchemy\Phrasea\Core\Event\OrderEvent;
use Alchemy\Phrasea\Core\PhraseaEvents;
@@ -30,6 +31,8 @@ use Symfony\Component\HttpFoundation\Response;
class Order implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
*/
@@ -37,9 +40,7 @@ class Order implements ControllerProviderInterface
{
$app['controller.prod.order'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('order');

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\Prod\type;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -21,6 +22,8 @@ use Symfony\Component\HttpFoundation\Response;
class Property implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
*/
@@ -28,9 +31,7 @@ class Property implements ControllerProviderInterface
{
$app['controller.prod.property'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireNotGuest();

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\Prod\record_adapter;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\PushEvent;
use Alchemy\Phrasea\Core\Event\ValidationEvent;
use Alchemy\Phrasea\Core\PhraseaEvents;
@@ -33,6 +34,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class Push implements ControllerProviderInterface
{
use ControllerProviderTrait;
protected function getUserFormatter(Application $app)
{
return function (User $user) use ($app) {
@@ -105,9 +108,7 @@ class Push implements ControllerProviderInterface
{
$app['controller.prod.push'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('push');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
use Silex\Application;
@@ -21,13 +22,13 @@ use Symfony\Component\HttpFoundation\Response;
class Query implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.query'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->post('/', 'controller.prod.query:query')
->bind('prod_query');

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Silex\Application;
use Silex\ControllerProviderInterface;
@@ -20,6 +21,8 @@ use Symfony\Component\HttpFoundation\JsonResponse;
class Records implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
*/
@@ -27,9 +30,7 @@ class Records implements ControllerProviderInterface
{
$app['controller.prod.records'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->match('/', 'controller.prod.records:getRecord')
->bind('record_details')

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -18,6 +19,8 @@ use Symfony\Component\HttpFoundation\Response;
class Share implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
*/
@@ -25,9 +28,7 @@ class Share implements ControllerProviderInterface
{
$app['controller.prod.share'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireNotGuest();

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\Exception as ControllerException;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\StoryWZ;
use Alchemy\Phrasea\Core\Event\RecordEdit;
use Alchemy\Phrasea\Core\PhraseaEvents;
@@ -24,13 +25,13 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class Story implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.story'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->get('/create/', function (Application $app) {
return $app['twig']->render('prod/Story/Create.html.twig', []);

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Exception\RuntimeException;
use DataURI;
use PHPExiftool\Exception\ExceptionInterface as PHPExiftoolException;
@@ -21,13 +22,13 @@ use Symfony\Component\HttpFoundation\Request;
class Tools implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.tools'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('doctools');

View File

@@ -11,21 +11,21 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\Basket;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Symfony\Component\HttpFoundation\Request;
use Silex\Application;
use Silex\ControllerProviderInterface;
class Tooltip implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.tooltip'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->post('/basket/{basket}/', 'controller.prod.tooltip:displayBasket')
->assert('basket', '\d+')

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Border\File;
use Alchemy\Phrasea\Border\Attribute\Status;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Event\LazaretEvent;
use Alchemy\Phrasea\Core\Event\RecordEdit;use Alchemy\Phrasea\Core\PhraseaEvents;
use DataURI\Parser;
@@ -28,6 +29,8 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class Upload implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* Connect the ControllerCollection to the Silex Application
*
@@ -38,9 +41,7 @@ class Upload implements ControllerProviderInterface
{
$app['controller.prod.upload'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireRight('addrecord');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\UsrList;
use Alchemy\Phrasea\Model\Entities\UsrListEntry;
use Alchemy\Phrasea\Model\Entities\UsrListOwner;
@@ -23,13 +24,13 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class UsrLists implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.usr-lists'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->get('/all/', 'controller.prod.usr-lists:getAll')
->bind('prod_lists_all');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\Basket;
use Alchemy\Phrasea\Model\Entities\StoryWZ;
use Alchemy\Phrasea\Helper\WorkZone as WorkzoneHelper;
@@ -23,13 +24,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class WorkZone implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.prod.workzone'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers
// Silex\Route::convert is not used as this should be done prior the before middleware

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Report;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Response\CSVFileResponse;
use Goodby\CSV\Export\Standard\Collection\CallbackCollection;
use Silex\Application;
@@ -21,13 +22,13 @@ use Symfony\Component\HttpFoundation\JsonResponse;
class Activity implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.report.activity'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('report');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Report;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Response\CSVFileResponse;
use Goodby\CSV\Export\Standard\Collection\CallbackCollection;
use Silex\Application;
@@ -20,13 +21,13 @@ use Symfony\Component\HttpFoundation\JsonResponse;
class Informations implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.report.informations'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('report');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Report;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\Response\CSVFileResponse;
use Goodby\CSV\Export\Standard\Collection\CallbackCollection;
use Silex\Application;
@@ -21,13 +22,13 @@ use Symfony\Component\HttpFoundation\JsonResponse;
class Root implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.report'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('report');

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Root;
use Alchemy\Geonames\Exception\ExceptionInterface as GeonamesExceptionInterface;
use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\ControllerProvider\Root\Login;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Model\Entities\FtpCredential;
@@ -29,13 +30,13 @@ use Symfony\Component\HttpFoundation\Response;
class Account implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$controllers = $app['controllers_factory'];
$app['account.controller'] = $this;
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
// Displays current logged in user account
$controllers->get('/', 'account.controller:displayAccount')

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Root;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Model\Entities\ApiApplication;
use Silex\Application;
@@ -21,13 +22,13 @@ use Symfony\Component\HttpFoundation\Response;
class Developers implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.account.developers'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->get('/applications/', 'controller.account.developers:listApps')
->bind('developers_applications');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\Thesaurus;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Doctrine\DBAL\Driver\Connection;
use Silex\Application;
use Silex\ControllerProviderInterface;
@@ -19,13 +20,13 @@ use Symfony\Component\HttpFoundation\Response;
class Thesaurus implements ControllerProviderInterface
{
use ControllerProviderTrait;
public function connect(Application $app)
{
$app['controller.thesaurus'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function () use ($app) {
$app['firewall']->requireAccessToModule('thesaurus');

View File

@@ -11,9 +11,10 @@
namespace Alchemy\Phrasea\ControllerProvider\Thesaurus;
use Alchemy\Phrasea\Controller\Thesaurus\caption_field;
use Alchemy\Phrasea\Controller\Thesaurus\caption_Field_Value;
use Alchemy\Phrasea\Controller\Thesaurus\databox;
use caption_field;
use caption_Field_Value;
use databox;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Model\Entities\User;
use Silex\Application;
use Silex\ControllerProviderInterface;
@@ -22,15 +23,15 @@ use Symfony\Component\HttpFoundation\Response;
class Xmlhttp implements ControllerProviderInterface
{
use ControllerProviderTrait;
const SEARCH_REPLACE_MAXREC = 25;
public function connect(Application $app)
{
$app['controller.thesaurus.xmlhttp'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->match('acceptcandidates.j.php', 'controller.thesaurus.xmlhttp:AcceptCandidatesJson')
->before(function () use ($app) {

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\User;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -18,6 +19,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
class Notifications implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
@@ -26,9 +28,7 @@ class Notifications implements ControllerProviderInterface
{
$app['controller.user.notifications'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->before(function (Request $request) use ($app) {
$app['firewall']->requireNotGuest();

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\ControllerProvider\User;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -18,6 +19,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
class Preferences implements ControllerProviderInterface
{
use ControllerProviderTrait;
/**
* {@inheritDoc}
@@ -26,9 +28,7 @@ class Preferences implements ControllerProviderInterface
{
$app['controller.user.preferences'] = $this;
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers = $this->createAuthenticatedCollection($app);
$controllers->post('/', 'controller.user.preferences:saveUserPref')
->bind('save_pref');

View File

@@ -11,6 +11,8 @@
namespace Alchemy\Phrasea\Feed;
use Alchemy\Phrasea\Model\Entities\FeedEntry;
interface FeedInterface
{
/**
@@ -33,7 +35,7 @@ interface FeedInterface
* @param integer $offset_start
* @param integer $how_many
*
* @return \Doctrine\Common\Collections\Collection
* @return FeedEntry[]
*/
public function getEntries($offset_start = 0, $how_many = null);

View File

@@ -299,7 +299,7 @@ class Feed implements FeedInterface
*
* @param Application $app
*
* @return type
* @return \collection
*/
public function getCollection(Application $app)
{
@@ -313,7 +313,7 @@ class Feed implements FeedInterface
*
* @param \collection $collection
*
* @return type
* @return void
*/
public function setCollection(\collection $collection = null)
{

View File

@@ -2,6 +2,7 @@
namespace Alchemy\Phrasea\Model\Repositories;
use Alchemy\Phrasea\Model\Entities\ApiApplication;
use Alchemy\Phrasea\Model\Entities\User;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr;
@@ -14,6 +15,11 @@ use Doctrine\ORM\Query\Expr;
*/
class ApiApplicationRepository extends EntityRepository
{
/**
* @param $clientId
* @return ApiApplication
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function findByClientId($clientId)
{
$qb = $this->createQueryBuilder('app');
@@ -41,6 +47,10 @@ class ApiApplicationRepository extends EntityRepository
return $qb->getQuery()->getResult();
}
/**
* @param User $user
* @return ApiApplication[]
*/
public function findAuthorizedAppsByUser(User $user)
{
$qb = $this->createQueryBuilder('app');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\Model\Repositories;
use Alchemy\Phrasea\Model\Entities\Feed;
use Doctrine\ORM\EntityRepository;
/**
@@ -24,7 +25,7 @@ class FeedRepository extends EntityRepository
/**
* Returns all the feeds a user can access.
*
* @return \Doctrine\Common\Collections\Collection
* @return Feed[]
*/
public function getAllForUser(\ACL $userACL, array $restrictions = [])
{

View File

@@ -245,7 +245,7 @@ class SearchEngineOptions
* Returns an array containing all the databoxes where the search will
* happen
*
* @return array
* @return \databox[]
*/
public function getDataboxes()
{

View File

@@ -58,13 +58,16 @@ class caption_record implements caption_interface, cache_cacheableInterface
return $this->record;
}
/**
* @return \caption_field[]
* @throws \Doctrine\DBAL\DBALException
*/
protected function retrieve_fields()
{
if (is_array($this->fields)) {
return $this->fields;
}
$fields = [];
try {
$fields = $this->get_data_from_cache();
} catch (\Exception $e) {
@@ -97,11 +100,10 @@ class caption_record implements caption_interface, cache_cacheableInterface
}
/**
*
* @param array $grep_fields
* @param Boolean $IncludeBusiness
*
* @return array
* @return \caption_field[]
*/
public function get_fields(Array $grep_fields = null, $IncludeBusiness = false)
{

View File

@@ -527,7 +527,7 @@ class databox_field implements cache_cacheableInterface
/**
*
* @return \PHPExiftool\Driver\Tag
* @return TagInterface
*/
public function get_tag()
{

View File

@@ -27,6 +27,7 @@ use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\Collections\ArrayCollection;
use MediaVorus\Media\MediaInterface;
use MediaVorus\MediaVorus;
use Rhumsaa\Uuid\Uuid;
use Alchemy\Phrasea\Model\RecordInterface;
@@ -755,7 +756,6 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
}
/**
*
* @return caption_record
*/
public function get_caption()
@@ -1722,8 +1722,8 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
public function get_container_baskets(EntityManager $em, User $user)
{
return $em
->getRepository('Phraseanet:Basket')
->findContainingRecordForUser($this, $user);
->getRepository('Phraseanet:Basket')
->findContainingRecordForUser($this, $user);
}
/**

View File

@@ -4,6 +4,7 @@ namespace Alchemy\Tests\Phrasea\Controller\Api;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Border\File;
use Alchemy\Phrasea\Controller\Api\V1Controller;
use Alchemy\Phrasea\ControllerProvider\Api\V1;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Authentication\Context;
@@ -981,7 +982,7 @@ abstract class ApiTestCase extends \PhraseanetWebTestCase
$this->assertArrayHasKey('embed', $content['response']);
$embedTypes = array_flip(array_map(function($subdef) {return $subdef['name'];},$content['response']['embed']));
$embedTypes = array_flip(array_map(function($subdef) {return $subdef['name'];}, $content['response']['embed']));
//access to all subdefs
$this->assertArrayHasKey('document', $embedTypes);
@@ -1895,7 +1896,7 @@ abstract class ApiTestCase extends \PhraseanetWebTestCase
protected function evaluateGoodUserItem($data, User $user)
{
foreach ([
'@entity@' => V1::OBJECT_TYPE_USER,
'@entity@' => V1Controller::OBJECT_TYPE_USER,
'id' => $user->getId(),
'email' => $user->getEmail() ?: null,
'login' => $user->getLogin() ?: null,
@@ -2397,7 +2398,7 @@ abstract class ApiTestCase extends \PhraseanetWebTestCase
$this->assertArrayHasKey('thumbnail', $story);
$this->assertArrayHasKey('uuid', $story);
$this->assertArrayHasKey('@entity@', $story);
$this->assertEquals(V1::OBJECT_TYPE_STORY, $story['@entity@']);
$this->assertEquals(V1Controller::OBJECT_TYPE_STORY, $story['@entity@']);
$this->assertTrue(Uuid::isValid($story['uuid']));
if ( ! is_null($story['thumbnail'])) {
@@ -2430,7 +2431,7 @@ abstract class ApiTestCase extends \PhraseanetWebTestCase
}
$this->assertArrayHasKey('@entity@', $story['metadatas']);
$this->assertEquals(V1::OBJECT_TYPE_STORY_METADATA_BAG, $story['metadatas']['@entity@']);
$this->assertEquals(V1Controller::OBJECT_TYPE_STORY_METADATA_BAG, $story['metadatas']['@entity@']);
foreach ($story['records'] as $record) {
$this->evaluateGoodRecord($record);