diff --git a/config/nginx.rewrite.rules b/config/nginx.rewrite.rules index 5e54b68b17..069105ae8b 100644 --- a/config/nginx.rewrite.rules +++ b/config/nginx.rewrite.rules @@ -45,6 +45,8 @@ rewrite ^/prod/notifications/.*$ /prod/router.php last; rewrite ^/robots.txt$ /index.php last; rewrite ^/feeds/.*$ /index.php last; +rewrite ^/account/.*$ /index.php last; +rewrite ^/developers/.*$ /index.php last; rewrite ^/lightbox/.*$ /lightbox/index.php last; rewrite ^/api/v1/.*$ /api/v1/index.php last; diff --git a/lib/Alchemy/Phrasea/Application/OAuth2.php b/lib/Alchemy/Phrasea/Application/OAuth2.php index 833226f731..b6f58a20cf 100644 --- a/lib/Alchemy/Phrasea/Application/OAuth2.php +++ b/lib/Alchemy/Phrasea/Application/OAuth2.php @@ -203,206 +203,6 @@ return call_user_func(function() { return; }); - /* **************************************************************** - * MANAGEMENT APPS - * - * - */ - /** - * list of all authorized apps by logged user - */ - $route = '/applications'; - $app->get($route, function() use ($app) { - $apps = \API_OAuth2_Application::load_app_by_user($app['appbox'], $app['Core']->getAuthenticatedUser()); - - return $app['response']('api/auth/applications.twig', array("apps" => $apps, 'user' => $app['Core']->getAuthenticatedUser())); - }); - - /** - * list of apps created by user - */ - $route = "/applications/dev"; - $app->get($route, function() use ($app) { - $rs = \API_OAuth2_Application::load_dev_app_by_user($app['appbox'], $app['Core']->getAuthenticatedUser()); - - return $app['response']('api/auth/application_dev.twig', array("apps" => $rs)); - }); - - /** - * display a new app form - */ - $route = "/applications/dev/new"; - $app->get($route, function() use ($app) { - $var = array("violations" => null, 'form' => null, 'request' => $app['request']); - - return $app['response']('api/auth/application_dev_new.twig', $var); - }); - - $route = "/applications/dev/create"; - $app->post($route, function() use ($app) { - $submit = false; - if ($app['request']->get("type") == "desktop") { - $post = new \API_OAuth2_Form_DevAppDesktop($app['request']); - } else { - $post = new \API_OAuth2_Form_DevAppInternet($app['request']); - } - - $violations = $app['validator']->validate($post); - - if ($violations->count() == 0) - $submit = true; - - $request = $app['request']; - - if ($submit) { - $application = \API_OAuth2_Application::create($app['appbox'], $app['Core']->getAuthenticatedUser(), $post->getName()); - $application->set_description($post->getDescription()) - ->set_redirect_uri($post->getSchemeCallback() . $post->getCallback()) - ->set_type($post->getType()) - ->set_website($post->getSchemeWebsite() . $post->getWebsite()); - - return $app->redirect("/api/oauthv2/applications/dev/" . $application->get_id() . "/show"); - } - - $var = array( - "violations" => $violations, - "form" => $post - ); - return $app['response']('api/auth/application_dev_new.twig', $var); - }); - - /** - * show details of app identified by its id - */ - $route = "/applications/dev/{id}/show"; - $app->get($route, function($id) use ($app) { - $client = new \API_OAuth2_Application($app['appbox'], $id); - $token = $client->get_user_account($app['Core']->getAuthenticatedUser())->get_token()->get_value(); - $var = array("app" => $client, "user" => $app['Core']->getAuthenticatedUser(), "token" => $token); - - return $app['response']('api/auth/application_dev_show.twig', $var); - })->assert('id', '\d+'); - - /** - * revoke access from a user to the app - * identified by account id - */ - $route = "/applications/revoke_access/"; - $app->post($route, function() use ($app) { - $result = array("ok" => false); - try { - $account = new \API_OAuth2_Account($app['appbox'], $app['request']->get('account_id')); - $account->set_revoked((bool) $app['request']->get('revoke')); - $result['ok'] = true; - } catch (\Exception $e) { - - } - - $Serializer = $app['Core']['Serializer']; - - return new Response( - $Serializer->serialize($result, 'json') - , 200 - , array("content-type" => "application/json") - ); - }); - - /** - * revoke access from a user to the app - * identified by account id - */ - $route = "/applications/{appId}/grant_password/"; - $app->post($route, function($appId) use ($app) { - $result = array("ok" => false); - try { - $client = new \API_OAuth2_Application($app['appbox'], $appId); - $client->set_grant_password((bool) $app['request']->get('grant')); - $result['ok'] = true; - } catch (\Exception $e) { - - } - - $Serializer = $app['Core']['Serializer']; - - return new Response( - $Serializer->serialize($result, 'json') - , 200 - , array("content-type" => "application/json") - ); - }); - - $route = "/applications/{id}/generate_access_token/"; - $app->post($route, function($id) use ($app) { - $result = array("ok" => false); - try { - $client = new \API_OAuth2_Application($app['appbox'], $id); - $account = $client->get_user_account($app['Core']->getAuthenticatedUser()); - - $token = $account->get_token(); - - if ($token instanceof API_OAuth2_Token) - $token->renew(); - else - $token = \API_OAuth2_Token::create($app['appbox'], $account); - - $result = array( - "ok" => true - , 'token' => $token->get_value() - ); - } catch (\Exception $e) { - - } - - $Serializer = $app['Core']['Serializer']; - - return new Response( - $Serializer->serialize($result, 'json') - , 200 - , array("content-type" => "application/json") - ); - })->assert('id', '\d+'); - - $route = "/applications/oauth_callback"; - $app->post($route, function() use ($app) { - $app_id = $app['request']->request->get("app_id"); - $app_callback = $app["request"]->request->get("callback"); - $result = array("success" => false); - try { - $client = new \API_OAuth2_Application($app['appbox'], $app_id); - $client->set_redirect_uri($app_callback); - $result['success'] = true; - } catch (\Exception $e) { - - } - - $Serializer = $app['Core']['Serializer']; - - return new Response( - $Serializer->serialize($result, 'json') - , 200 - , array("content-type" => "application/json") - ); - }); - - $route = "/applications/{id}"; - $app->delete($route, function($id) use ($app) { - $result = array("success" => false); - try { - $client = new \API_OAuth2_Application($app['appbox'], $id); - $client->delete(); - $result['success'] = true; - } catch (\Exception $e) { - - } - - $Serializer = $app['Core']['Serializer']; - - return new Response( - $Serializer->serialize($result, 'json') - , 200 - , array("content-type" => "application/json") - ); - })->assert('id', '\d+'); /** * ******************************************************************* * diff --git a/lib/Alchemy/Phrasea/Application/Root.php b/lib/Alchemy/Phrasea/Application/Root.php index e0dc12507f..5b8ed6f7ae 100644 --- a/lib/Alchemy/Phrasea/Application/Root.php +++ b/lib/Alchemy/Phrasea/Application/Root.php @@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Application; use Alchemy\Phrasea\Controller\Root as Controller; use Silex\Application as SilexApp; +use Silex\Provider\ValidatorServiceProvider; use Symfony\Component\HttpFoundation\Response; /** @@ -25,12 +26,10 @@ return call_user_func(function() { $app['Core'] = \bootstrap::getCore(); + $app->register(new ValidatorServiceProvider()); + $app->before(function () use ($app) { - // redirect the user to the setup screen - // if Phraseanet in not set up - if ( ! \setup::is_installed()) { - return $app->redirect("/setup/"); - } + $app['Core']['Firewall']->requireSetup($app); }); $app->get('/', function(SilexApp $app) { @@ -60,6 +59,7 @@ return call_user_func(function() { $app->mount('/feeds/', new Controller\RSSFeeds()); $app->mount('/account/', new Controller\Account()); + $app->mount('/developers/', new Controller\Developers()); return $app; } diff --git a/lib/Alchemy/Phrasea/Controller/Root/Account.php b/lib/Alchemy/Phrasea/Controller/Root/Account.php index 5398dee067..22dfc7b93f 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Account.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Account.php @@ -15,6 +15,7 @@ use Silex\Application; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; /** * @@ -28,8 +29,6 @@ class Account implements ControllerProviderInterface { $controllers = $app['controllers_factory']; - require_once $app['Core']['Registry']->get('GV_RootPath') . 'lib/classes/deprecated/inscript.api.php'; - $controllers->before(function() use ($app) { $app['Core']['Firewall']->requireAuthentication($app); }); @@ -95,9 +94,156 @@ class Account implements ControllerProviderInterface $controllers->post('/', $this->call('updateAccount')) ->bind('update_account'); + /** + * Give account access + * + * name : account_access + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/access/', $this->call('accountAccess')) + ->bind('account_access'); + + /** + * Give account open sessions + * + * name : account_sessions + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/security/sessions/', $this->call('accountSessionsAccess')) + ->bind('account_sessions'); + + /** + * Give authorized applications that can access user informations + * + * name : account_auth_apps + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/security/applications/', $this->call('accountAuthorizedApps')) + ->bind('account_auth_apps'); + + /** + * Grant access to an authorized app + * + * name : grant_app_access + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/security/application/{application_id}/grant/', $this->call('grantAccess')) + ->assert('application_id', '\d+') + ->bind('grant_app_access'); + return $controllers; } + /** + * Display authorized applications that can access user informations + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function grantAccess(Application $app, Request $request, $application_id) + { + if ( ! $request->isXmlHttpRequest() || ! array_key_exists($request->getMimeType('json'), array_flip($request->getAcceptableContentTypes()))) { + $app->abort(400, _('Bad request format, only JSON is allowed')); + } + + $appbox = \appbox::get_instance($app['Core']); + $error = false; + + try { + $account = \API_OAuth2_Account::load_with_user( + $appbox + , new \API_OAuth2_Application($appbox, $application_id) + , $app['Core']->getAuthenticatedUser() + ); + } catch (\Exception_NotFound $e) { + $error = true; + } + + $account->set_revoked((bool) $request->get('revoke'), false); + + return new JsonResponse(array('success' => ! $error)); + } + + /** + * Display authorized applications that can access user informations + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function accountAuthorizedApps(Application $app, Request $request) + { + $user = $app['Core']->getAuthenticatedUser(); + + return $app['Core']['Twig']->render('account/authorized_apps.html.twig', array( + "apps" => \API_OAuth2_Application::load_app_by_user(\appbox::get_instance($app['Core']), $user), + 'user' => $user + )); + } + + /** + * Display account session accesss + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function accountSessionsAccess(Application $app, Request $request) + { + return new Response($app['Core']['Twig']->render('account/sessions.html.twig')); + } + + /** + * Display account base access + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function accountAccess(Application $app, Request $request) + { + require_once $app['Core']['Registry']->get('GV_RootPath') . 'lib/classes/deprecated/inscript.api.php'; + + $user = $app['Core']->getAuthenticatedUser(); + + return new Response($app['Core']['Twig']->render('account/access.html.twig', array( + 'inscriptions' => giveMeBases($user->get_id()) + ))); + } + /** * Display account form * @@ -127,11 +273,10 @@ class Account implements ControllerProviderInterface break; } - return new Response($app['Core']['Twig']->render('user/account.html.twig', array( + return new Response($app['Core']['Twig']->render('account/account.html.twig', array( 'geonames' => new \geonames(), 'user' => $user, 'notice' => $notice, - 'inscriptions' => giveMeBases($user->get_id()), 'evt_mngr' => $evtMngr, 'notifications' => $evtMngr->list_notifications_available($user->get_id()), ))); diff --git a/lib/Alchemy/Phrasea/Controller/Root/Developers.php b/lib/Alchemy/Phrasea/Controller/Root/Developers.php new file mode 100644 index 0000000000..3aeb51cb4d --- /dev/null +++ b/lib/Alchemy/Phrasea/Controller/Root/Developers.php @@ -0,0 +1,416 @@ +before(function() use ($app) { + $app['Core']['Firewall']->requireAuthentication($app); + }); + + /** + * List of apps created by the user + * + * name : list_dev_apps + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/applications/', $this->call('listApps')) + ->bind('list_dev_apps'); + + + + /** + * Get the form to create a new application + * + * name : form_dev_app + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/application/new/', $this->call('displayFormApp')) + ->bind('form_dev_app'); + + /** + * Create a new app + * + * name : create_dev_app + * + * description : Display form to create a new account + * + * method : POST + * + * parameters : none + * + * return : HTML Response + */ + $controllers->post('/application/', $this->call('newApp')) + ->bind('create_dev_app'); + + + /** + * Get application information + * + * name : get_dev_app + * + * description : Display form to create a new account + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->get('/application/{id}/', $this->call('getApp')) + ->assert('id', '\d+') + ->bind('get_dev_app'); + + /** + * Delete application + * + * name : delete_dev_app + * + * description : Delete selected application + * + * method : GET + * + * parameters : none + * + * return : HTML Response + */ + $controllers->delete('/application/{id}/', $this->call('deleteApp')) + ->assert('id', '\d+') + ->bind('delete_dev_app'); + + /** + * Authorize application to use a grant password type, which allow end user to + * authenticate himself with their credentials (login/password) + * + * name : grant_password_auth + * + * description : Display form to create a new account + * + * method : POST + * + * parameters : none + * + * return : HTML Response + */ + $controllers->post('/application/{id}/authorize_grant_password/', $this->call('authorizeGrantpassword')) + ->assert('id', '\d+') + ->bind('grant_password_auth'); + + /** + * Renew access token + * + * name : renew_access_token + * + * description : Regenerate an access token for the current app linked to the authenticated user + * + * method : POST + * + * parameters : none + * + * return : HTML Response + */ + $controllers->post('/application/{id}/access_token/', $this->call('renewAccessToken')) + ->assert('id', '\d+') + ->bind('renew_access_token'); + + /** + * Renew access token + * + * name : renew_app_callback + * + * description : Regenerate an access token for the current app linked to the authenticated user + * + * method : POST + * + * parameters : none + * + * return : HTML Response + */ + $controllers->post('/application/{id}/callback/', $this->call('renewAppCallback')) + ->assert('id', '\d+') + ->bind('renew_app_callback'); + + return $controllers; + } + + /** + * Delete application + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * @param integer $id The application id + * + * @return Response + */ + public function deleteApp(Application $app, Request $request, $id) + { + if ( ! $request->isXmlHttpRequest() || ! array_key_exists($request->getMimeType('json'), array_flip($request->getAcceptableContentTypes()))) { + $app->abort(400, _('Bad request format, only JSON is allowed')); + } + + $error = false; + + try { + $clientApp = new \API_OAuth2_Application(\appbox::get_instance($app['Core']), $id); + $clientApp->delete(); + } catch (\Exception_NotFound $e) { + $error = true; + } + + return new JsonResponse(array('success' => ! $error)); + } + + /** + * Change application callback + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * @param integer $id The application id + * + * @return Response + */ + public function renewAppCallback(Application $app, Request $request, $id) + { + if ( ! $request->isXmlHttpRequest() || ! array_key_exists($request->getMimeType('json'), array_flip($request->getAcceptableContentTypes()))) { + $app->abort(400, _('Bad request format, only JSON is allowed')); + } + + $error = false; + + try { + $clientApp = new \API_OAuth2_Application(\appbox::get_instance($app['Core']), $id); + + if ($callback = $request->get("callback")) { + $clientApp->set_redirect_uri($callback); + } else { + $error = true; + } + } catch (\Exception_NotFound $e) { + $error = true; + } + + return new JsonResponse(array('success' => ! $error)); + } + + /** + * Authorize application to use a grant password type + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * @param integer $id The application id + * + * @return Response + */ + public function renewAccessToken(Application $app, Request $request, $id) + { + if ( ! $request->isXmlHttpRequest() || ! array_key_exists($request->getMimeType('json'), array_flip($request->getAcceptableContentTypes()))) { + $app->abort(400, _('Bad request format, only JSON is allowed')); + } + + $appbox = \appbox::get_instance($app['Core']); + $error = false; + $accessToken = null; + + try { + $clientApp = new \API_OAuth2_Application($appbox, $id); + $account = $clientApp->get_user_account($app['Core']->getAuthenticatedUser()); + + $token = $account->get_token(); + + if ($token instanceof \API_OAuth2_Token) { + $token->renew(); + } else { + $token = \API_OAuth2_Token::create($appbox, $account); + } + + $accessToken = $token->get_value(); + } catch (\Exception $e) { + $error = true; + } + + return new JsonResponse(array('success' => ! $error, 'token' => $accessToken)); + } + + /** + * Authorize application to use a grant password type + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * @param integer $id The application id + * + * @return Response + */ + public function authorizeGrantpassword(Application $app, Request $request, $id) + { + if ( ! $request->isXmlHttpRequest() || ! array_key_exists($request->getMimeType('json'), array_flip($request->getAcceptableContentTypes()))) { + $app->abort(400, _('Bad request format, only JSON is allowed')); + } + + $error = false; + + try { + $clientApp = new \API_OAuth2_Application(\appbox::get_instance($app['Core']), $id); + } catch (\Exception_NotFound $e) { + $error = true; + } + + $clientApp->set_grant_password((bool) $request->get('grant', false)); + + return new JsonResponse(array('success' => ! $error)); + } + + /** + * Create a new developer applications + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function newApp(Application $app, Request $request) + { + $error = false; + + if ($request->get("type") == "desktop") { + $form = new \API_OAuth2_Form_DevAppDesktop($app['request']); + } else { + $form = new \API_OAuth2_Form_DevAppInternet($app['request']); + } + + $violations = $app['validator']->validate($form); + + if ($violations->count() == 0) { + $error = true; + } + + if ($error) { + $application = \API_OAuth2_Application::create(\appbox::get_instance($app['Core']), $app['Core']->getAuthenticatedUser(), $form->getName()); + $application + ->set_description($form->getDescription()) + ->set_redirect_uri($form->getSchemeCallback() . $form->getCallback()) + ->set_type($form->getType()) + ->set_website($form->getSchemeWebsite() . $form->getWebsite()); + + return $app->redirect(sprintf('/developers/application/%d/', $application->get_id())); + } + + $var = array( + "violations" => $violations, + "form" => $form + ); + + return $app['Core']['Twig']->render('/developers/application.html.twig', $var); + } + + /** + * List of apps created by the user + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function listApps(Application $app, Request $request) + { + return $app['Core']['Twig']->render('developers/applications.html.twig', array( + "apps" => \API_OAuth2_Application::load_dev_app_by_user( + \appbox::get_instance($app['Core']), $app['Core']->getAuthenticatedUser() + ))); + } + + /** + * Display form application + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * + * @return Response + */ + public function displayFormApp(Application $app, Request $request) + { + return $app['Core']['Twig']->render('developers/application_form.html.twig', array( + "violations" => null, + 'form' => null, + 'request' => $request + )); + } + + /** + * Get application information + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * @param integer $id The application id + * + * @return Response + */ + public function getApp(Application $app, Request $request, $id) + { + $user = $app['Core']->getAuthenticatedUser(); + + try { + $client = new \API_OAuth2_Application(\appbox::get_instance($app['Core']), $id); + } catch (\Exception_NotFound $e) { + $app->abort(404); + } + + $token = $client->get_user_account($user)->get_token()->get_value(); + + return $app['Core']['Twig']->render('developers/application.html.twig', array( + "app" => $client, + "user" => $user, + "token" => $token + )); + } + + /** + * Prefix the method to call with the controller class name + * + * @param string $method The method to call + * @return string + */ + private function call($method) + { + return sprintf('%s::%s', __CLASS__, $method); + } +} diff --git a/lib/Alchemy/Phrasea/Security/Firewall.php b/lib/Alchemy/Phrasea/Security/Firewall.php index 2590eb07f7..e73185172e 100644 --- a/lib/Alchemy/Phrasea/Security/Firewall.php +++ b/lib/Alchemy/Phrasea/Security/Firewall.php @@ -7,6 +7,13 @@ use Silex\Application; class Firewall { + public function requireSetUp(Application $app) + { + if ( ! \setup::is_installed()) { + return $app->redirect("/setup/"); + } + } + public function requireAuthentication(Application $app) { if ($app['Core']->isAuthenticated()) { @@ -23,7 +30,7 @@ class Firewall } if ($app['Core']->getAuthenticatedUser()->is_guest()) { - + return $app->redirect('/login/'); } } diff --git a/lib/classes/API/OAuth2/Account.class.php b/lib/classes/API/OAuth2/Account.class.php index 09a65dec80..01ccb12b53 100644 --- a/lib/classes/API/OAuth2/Account.class.php +++ b/lib/classes/API/OAuth2/Account.class.php @@ -281,8 +281,9 @@ class API_OAuth2_Account $row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->closeCursor(); - if ( ! $row) + if ( ! $row) { throw new Exception_NotFound(); + } return new self($appbox, $row['api_account_id']); } diff --git a/lib/classes/API/OAuth2/Application.class.php b/lib/classes/API/OAuth2/Application.class.php index ea09d36da1..b756786293 100644 --- a/lib/classes/API/OAuth2/Application.class.php +++ b/lib/classes/API/OAuth2/Application.class.php @@ -145,6 +145,11 @@ class API_OAuth2_Application $stmt = $this->appbox->get_connection()->prepare($sql); $stmt->execute(array(':application_id' => $this->id)); + + if (0 === $stmt->rowCount()) { + throw new \Exception_NotFound(sprintf('Application with id %d not found', $this->id)); + } + $row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->closeCursor(); $this->creator = ! $row['creator'] ? null : User_Adapter::getInstance($row['creator'], $this->appbox); diff --git a/templates/web/account/access.html.twig b/templates/web/account/access.html.twig new file mode 100644 index 0000000000..d1471f0f4d --- /dev/null +++ b/templates/web/account/access.html.twig @@ -0,0 +1,168 @@ +{% extends 'account/base.html.twig' %} + +{% block content %} +
+ + + + + + + {% for sbasId, baseInsc in inscriptions %} + {% if baseInsc['CollsRegistered'] or baseInsc['CollsRefuse'] or baseInsc['CollsWait'] or baseInsc['CollsIntime'] or baseInsc['CollsOuttime'] or baseInsc['CollsNonactif'] or baseInsc['CollsCGU'] or baseInsc['Colls'] %} + + + + {% endif %} + + {% if baseInsc['CollsRegistered'] is not none %} + {% for base in baseInsc['CollsRegistered']%} + {% for collId, isTrue in base %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + {% endfor %} + {% endfor %} + + + + {% endif %} + + {% if baseInsc['CollsRefuse'] %} + {% for collId, isTrue in baseInsc['CollsRefuse'] %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + {% endfor %} + + + + {% endif %} + + {% if baseInsc['CollsWait'] %} + {% for collId, isTrue in baseInsc['CollsWait'] %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + {% endfor %} + + {% endif %} + + {% if baseInsc['CollsIntime'] %} + {% for collId, isTrue in baseInsc['CollsIntime'] %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + {% endfor %} + + {% endif %} + + {% if baseInsc['CollsOuttime'] %} + {% for collId, isTrue in baseInsc['CollsOuttime'] %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + {% endfor %} + + {% endif %} + + {% if baseInsc['CollsNonactif'] %} + {% for collId, isTrue in baseInsc['CollsNonactif'] %} + {{ base_id == (sbasId |base_from_coll(collId)) }} + + + + {% endfor %} + + {% endif %} + + {% if (baseInsc['CollsCGU'] or baseInsc['Colls']) and baseInsc['inscript'] %} + {{ noDemand == false }} + {% if baseInsc['Colls'] %} + {% if baseInsc['CGU'] %} + + + + + + + {% endif %} + {% for collId, collName in baseInsc['Colls'] %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + + + {% endfor %} + {% endif %} + {% if baseInsc['CollsCGU'] %} + {% for collId, collDesc in baseInsc['CollsCGU'] %} + {{ base_id == sbasId |base_from_coll(collId) }} + + + + + + + + + + + + + + + {% endfor %} + {% endif %} + {% endif %} + {% endfor %} +
   

{{ sbasId | sbas_names }}

+ {% trans 'login::register: acces authorise sur la collection ' %}{{ sbasId |sbas_names }} + {% if isTrue | trim != '' %} + {% trans 'login::register::CGU: lire les CGU' %} + {% endif %} +
+
+ {% trans 'login::register: acces refuse sur la collection ' %}{{ sbasId |sbas_names }} + {% if isTrue | trim != '' %} + {% trans 'login::register::CGU: lire les CGU' %} + {% endif %} +
+
+ {% trans 'login::register: en attente d\'acces sur' %} {{ sbasId |sbas_names }} + {% if isTrue | trim != '' %} + {% trans 'login::register::CGU: lire les CGU' %} + {% endif %} +
+ {% trans 'login::register: acces temporaire sur' %} {{ sbasId |sbas_names }} + {% if isTrue |trim != '' %} + {% trans 'login::register::CGU: lire les CGU' %} + {% endif %} +
+ {% trans 'login::register: acces temporaire termine sur ' %}{{ sbasId |sbas_names }} + {% if isTrue |trim != '' %} + {% trans 'login::register::CGU: lire les CGU' %} + {% endif %} +
+ {% trans 'login::register: acces supendu sur' %} {{ sbasId |sbas_names }} + {% if isTrue |trim != '' %} + {% trans 'login::register::CGU: lire les CGU' %} + {% endif %} +
{% trans 'login::register: L\'acces aux bases ci-dessous implique l\'acceptation des Conditions Generales d\'Utilisation (CGU) suivantes' %}
{{ baseInsc['CGU'] }}
{{ collName }} + + {% trans 'login::register: Faire une demande d\'acces' %} +

{% trans 'login::register: L\'acces aux bases ci-dessous implique l\'acceptation des Conditions Generales d\'Utilisation (CGU) suivantes' %}
+
{{ collDesc['CGU'] }}
+
{{ collDesc['name'] }} + + {% trans 'login::register: Faire une demande d\'acces' %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/templates/web/account/account.html.twig b/templates/web/account/account.html.twig new file mode 100644 index 0000000000..f7e7d661b6 --- /dev/null +++ b/templates/web/account/account.html.twig @@ -0,0 +1,220 @@ +{% extends 'account/base.html.twig' %} + +{% block head %} + + +{% endblock %} + +{% block content %} + + + + +
+ {% if notice | trim != '' %} +
{{ notice }}
+ {% endif %} +
+
+ + {% trans 'Informations personnelles' %} + +
+ +
+

{{ user.get_login() }}

+

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ + +
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+
+

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+ + {% trans 'Notification par email' %} + {% for notification_group, nots in notifications%} +

{{ notification_group }}

+ {% for notification in nots %} +
+ +
+ +

+
+
+ {% endfor %} + {% endfor %} + + {% trans 'FTP' %} +
+ +
+ +

+
+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +

+
+
+
+ +
+ +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/web/account/authorized_apps.html.twig b/templates/web/account/authorized_apps.html.twig new file mode 100644 index 0000000000..d24dee9edc --- /dev/null +++ b/templates/web/account/authorized_apps.html.twig @@ -0,0 +1,107 @@ +{% extends 'account/base.html.twig' %} + +{% block head %} + +{% endblock %} +{% block content %} + + + + + + + +
+
+

{% trans 'Vous avez autorise ces applications a acceder a votre compte' %}

+ {% if apps|length > 0 %} +
    + {% for app in apps %} +
  • +
    + {% set account = app.get_user_account(user) %} + {% if account.is_revoked() is empty %} + + {% else %} + + {% endif %} + + + {{app.get_name()}} + + {% if user is not none %} + {% set user_name = app.get_creator().get_display_name() %} + {% trans %} + par {{user_name}} + {% endtrans %} + {% endif%} + + + {{app.get_created_on()|prettyDate}} + + {{app.get_description() }} +
    +
  • + {%endfor%} +
+ {% else %} +
+ {% trans 'Aucune application n\'a accés à vos données.' %} +
+ {% endif %} +
+
+
+

{% trans 'Applications' %}

+

+ {% trans 'Naviguez et gerez les applications que vous souhaitez autoriser a acceder a vos informations Phraseanet' %} +

+

{% trans 'Developpeurs' %}

+

+ {% trans 'Les developpeurs peuvent editer l\'enregistrement de leurs application grace a l\'onglet "developpeurs" ci-dessus' %} +

+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/web/account/base.html.twig b/templates/web/account/base.html.twig new file mode 100644 index 0000000000..18aadc36be --- /dev/null +++ b/templates/web/account/base.html.twig @@ -0,0 +1,44 @@ + + + {{ registry.get('GV_homeTitle') }} {% trans 'login:: Mon compte'%} + + + + + {% block head %}{% endblock %} + + + +
+
+ + + + + +
+ {{ registry.get('GV_homeTitle') }} + {% trans 'login:: Mon compte' %} + +
+
+
+ +
+ © Copyright Alchemy 2005-{{ "now"|date("Y") }} +
+
+
+ + diff --git a/templates/web/account/sessions.html.twig b/templates/web/account/sessions.html.twig new file mode 100644 index 0000000000..1af4b95bc5 --- /dev/null +++ b/templates/web/account/sessions.html.twig @@ -0,0 +1,67 @@ +{% extends 'account/base.html.twig' %} + +{% block content %} +
+ + + + + + + + + + + + + + + + + {% for row in session.get_my_sessions() %} + + + + + + + + + + {% endfor %} + +
+ {% trans 'Mes sessions' %} +
+ + {% trans 'Date de connexion' %} + + {% trans 'Dernier access' %} + + {% trans 'IP' %} + + {% trans 'Browser' %} + + {% trans 'ecran' %} + + {% trans 'Session persistante' %} +
+ {% if session.get_ses_id() != row['session_id'] %} + + {% endif %} + + {{ row['created_on'] |getDate }} + + {{ row['lastaccess'] |getDate }} + + {{ row['ip'] }} + {{ row['ip_infos'] }} + + {{ row['browser'] }} {{ row['browser_version'] }} + + {{ row['screen'] }} + + {% if row['token'] %}oui{% endif %} +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/web/developers/application.html.twig b/templates/web/developers/application.html.twig new file mode 100644 index 0000000000..7091ac0708 --- /dev/null +++ b/templates/web/developers/application.html.twig @@ -0,0 +1,90 @@ +{% extends 'account/base.html.twig' %} + +{% use "developers/header.html.twig" with header as parent_header %} + +{% block head %} + {{ block('parent_header') }} +{% endblock %} + +{% block content %} + +

{% trans 'Application' %}

+ +
+ +
+

{% trans 'settings OAuth' %}

+

{% trans 'Les parametres oauth de votre application.' %}

+ + + + + + + + + + + + + {% if app.get_type == constant('API_OAuth2_Application::DESKTOP_TYPE') %} + + {% else %} + + {%endif%} + + + + + + + + + + + + + + +
Client ID{{app.get_client_id}}
Client Secret{{app.get_client_secret}}
{% trans 'URL de callback' %} + {{app.get_redirect_uri}} + {{app.get_redirect_uri}} + + +
Authorize endpoint{{registry.get('GV_ServerName')}}api/oauthv2/authorize
Access endpoint{{registry.get('GV_ServerName')}}api/oauthv2/token
{% trans 'Activer le grant_type de type password pour votre application' %}
+ +

{% trans 'Votre token d\'access' %}

+

{% trans 'Les paramétres oauth de votre application.' %}

+ + + + + + + + + + + +
+ {% trans 'Token' %} + + + {% if not token is none %} + {{token|default('')}} + {% else %} + {% trans 'Le token n\'a pas encore ete genere' %} + {% endif %} + +
+
+ +
+{% endblock %} diff --git a/templates/web/developers/application_form.html.twig b/templates/web/developers/application_form.html.twig new file mode 100644 index 0000000000..ae62a9a555 --- /dev/null +++ b/templates/web/developers/application_form.html.twig @@ -0,0 +1,105 @@ +{% extends 'account/base.html.twig' %} + +{% use "developers/header.html.twig" with header as parent_header %} + +{% block head %} + {{ block('parent_header') }} +{% endblock %} + +{# form input macro #} +{% macro input(name, value, violations, property, type, size) %} + {% if violations is none %} + + {% else %} + {% set hasError = "false" %} + {% for violation in violations %} + {% if violation.getPropertyPath == property and hasError == "false" %} + {% set hasError = "true" %} + +
{{ violation.getInvalidValue }} - {{violation.getMessage}}
+ {% endif %} + {% endfor %} + {% if hasError == "false" %} + + {% endif %} + {% endif %} +{% endmacro %} + +{# form textare macro #} +{% macro textarea(name, value, violations,property, rows, cols) %} + {% if violations is none %} + + {% else %} + {% set hasError = "false" %} + {% for violation in violations %} + {% if violation.getPropertyPath == property and hasError == "false" %} + {% set hasError = "true" %} + +
{{violation.getMessage}}
+ {% endif %} + {% endfor %} + {% if hasError == "false" %} + + {% endif %} + {% endif %} +{% endmacro %} + +{% block content %} +
+ {% if form is none %} + {% set name, description, website, callback = '', '', '', ''%} + {% set app_type = 'web'%} + {% else %} + {% set name = form.name %} + {% set description = form.description %} + {% set website = form.website %} + {% set callback = form.callback %} + {% set app_type = form.type %} + {% endif %} + + + + + + + + + + + + + + + + + + {% if app_type == "web" %} + + + + + {% endif %} + + + +
{{ _self.input("name", name, violations, 'name') }}
{{ _self.textarea("description", description, 'description', violations, 5, 17) }}
+ + {{ _self.input("website", website, violations, 'urlwebsite') }}
{% trans 'Application web' %} + + {% trans 'Application desktop' %} +
+ + {{ _self.input("callback", callback, violations, 'urlcallback') }}
+
+
+ +
+{% endblock %} diff --git a/templates/web/developers/applications.html.twig b/templates/web/developers/applications.html.twig new file mode 100644 index 0000000000..0f9c67e725 --- /dev/null +++ b/templates/web/developers/applications.html.twig @@ -0,0 +1,62 @@ +{% extends 'account/base.html.twig' %} + +{% use "developers/header.html.twig" with header as parent_header %} + +{% block head %} + {{ block('parent_header') }} +{% endblock %} + +{% block content %} + + + + + + + +
+
+

Phraseanet Developper Center

+

{% trans 'Mes applications' %}

+ {% if apps|length > 0 %} +
    + {% for app in apps %} +
  • +
    + + + + + {{app.get_name()}} + + + + {{app.get_description() }} + {{app.get_website()}} +
    +
  • + {%endfor%} +
+ {% else %} +
+ {% trans 'Aucune application creee.' %} +
+ {% endif %} +
+
+
+
+ + +
+ {% trans 'Decouvrez la documentation' %} +
+
+ + +
+ {% trans 'Creez une application pour commencer a utiliser l\'API Phraseanet' %} +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/web/developers/header.html.twig b/templates/web/developers/header.html.twig new file mode 100644 index 0000000000..519ebe6d2f --- /dev/null +++ b/templates/web/developers/header.html.twig @@ -0,0 +1,177 @@ +{% block header %} + +{% endblock %} \ No newline at end of file diff --git a/templates/web/user/account.html.twig b/templates/web/user/account.html.twig deleted file mode 100644 index 43fd36a3d1..0000000000 --- a/templates/web/user/account.html.twig +++ /dev/null @@ -1,724 +0,0 @@ - - - {{ registry.get('GV_homeTitle') }} {% trans 'login:: Mon compte'%} - - - - - - - - - - -
-
- - - - - -
{{ registry.get('GV_homeTitle') }}{% trans 'login:: Mon compte' %} -
-
-
-
-
- - -
- - - - -
- {% if notice | trim != '' %} -
{{ notice }}
- {% endif %} -
-
- - {% trans 'Informations personnelles' %} - -
- -
-

{{ user.get_login() }}

-

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- - -
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
-
-

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
- - {% trans 'Notification par email' %} - {% for notification_group, nots in notifications%} -

{{ notification_group }}

- {% for notification in nots %} -
- -
- -

-
-
- {% endfor %} - {% endfor %} - - {% trans 'FTP' %} -
- -
- -

-
-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -

-
-
-
- -
- -
-
-
-
-
- - -
-
- - - - - - - {% for sbasId, baseInsc in inscriptions %} - {% if baseInsc['CollsRegistered'] or baseInsc['CollsRefuse'] or baseInsc['CollsWait'] or baseInsc['CollsIntime'] or baseInsc['CollsOuttime'] or baseInsc['CollsNonactif'] or baseInsc['CollsCGU'] or baseInsc['Colls'] %} - - - - {% endif %} - - {% if baseInsc['CollsRegistered'] is not none %} - {% for base in baseInsc['CollsRegistered']%} - {% for collId, isTrue in base %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - {% endfor %} - {% endfor %} - - - - {% endif %} - - {% if baseInsc['CollsRefuse'] %} - {% for collId, isTrue in baseInsc['CollsRefuse'] %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - {% endfor %} - - - - {% endif %} - - {% if baseInsc['CollsWait'] %} - {% for collId, isTrue in baseInsc['CollsWait'] %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - {% endfor %} - - {% endif %} - - {% if baseInsc['CollsIntime'] %} - {% for collId, isTrue in baseInsc['CollsIntime'] %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - {% endfor %} - - {% endif %} - - {% if baseInsc['CollsOuttime'] %} - {% for collId, isTrue in baseInsc['CollsOuttime'] %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - {% endfor %} - - {% endif %} - - {% if baseInsc['CollsNonactif'] %} - {% for collId, isTrue in baseInsc['CollsNonactif'] %} - {{ base_id == (sbasId |base_from_coll(collId)) }} - - - - {% endfor %} - - {% endif %} - - {% if (baseInsc['CollsCGU'] or baseInsc['Colls']) and baseInsc['inscript'] %} - {{ noDemand == false }} - {% if baseInsc['Colls'] %} - {% if baseInsc['CGU'] %} - - - - - - - {% endif %} - {% for collId, collName in baseInsc['Colls'] %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - - - {% endfor %} - {% endif %} - {% if baseInsc['CollsCGU'] %} - {% for collId, collDesc in baseInsc['CollsCGU'] %} - {{ base_id == sbasId |base_from_coll(collId) }} - - - - - - - - - - - - - - - {% endfor %} - {% endif %} - {% endif %} - {% endfor %} -
   

{{ sbasId | sbas_names }}

- {% trans 'login::register: acces authorise sur la collection ' %}{{ sbasId |sbas_names }} - {% if isTrue | trim != '' %} - {% trans 'login::register::CGU: lire les CGU' %} - {% endif %} -
-
- {% trans 'login::register: acces refuse sur la collection ' %}{{ sbasId |sbas_names }} - {% if isTrue | trim != '' %} - {% trans 'login::register::CGU: lire les CGU' %} - {% endif %} -
-
- {% trans 'login::register: en attente d\'acces sur' %} {{ sbasId |sbas_names }} - {% if isTrue | trim != '' %} - {% trans 'login::register::CGU: lire les CGU' %} - {% endif %} -
- {% trans 'login::register: acces temporaire sur' %} {{ sbasId |sbas_names }} - {% if isTrue |trim != '' %} - {% trans 'login::register::CGU: lire les CGU' %} - {% endif %} -
- {% trans 'login::register: acces temporaire termine sur ' %}{{ sbasId |sbas_names }} - {% if isTrue |trim != '' %} - {% trans 'login::register::CGU: lire les CGU' %} - {% endif %} -
- {% trans 'login::register: acces supendu sur' %} {{ sbasId |sbas_names }} - {% if isTrue |trim != '' %} - {% trans 'login::register::CGU: lire les CGU' %} - {% endif %} -
{% trans 'login::register: L\'acces aux bases ci-dessous implique l\'acceptation des Conditions Generales d\'Utilisation (CGU) suivantes' %}
{{ baseInsc['CGU'] }}
{{ collName }} - - {% trans 'login::register: Faire une demande d\'acces' %} -

{% trans 'login::register: L\'acces aux bases ci-dessous implique l\'acceptation des Conditions Generales d\'Utilisation (CGU) suivantes' %}
-
{{ collDesc['CGU'] }}
-
{{ collDesc['name'] }} - - {% trans 'login::register: Faire une demande d\'acces' %} -
- -
-
- - -
- - - - - - - - - - - - - - - - - {% for row in session.get_my_sessions() %} - - - - - - - - - - {% endfor %} - -
- {% trans 'Mes sessions' %} -
- - {% trans 'Date de connexion' %} - - {% trans 'Dernier access' %} - - {% trans 'IP' %} - - {% trans 'Browser' %} - - {% trans 'ecran' %} - - {% trans 'Session persistante' %} -
- {% if session.get_ses_id() != row['session_id'] %} - - {% endif %} - - {{ row['created_on'] |getDate }} - - {{ row['lastaccess'] |getDate }} - - {{ row['ip'] }} - {{ row['ip_infos'] }} - - {{ row['browser'] }} {{ row['browser_version'] }} - - {{ row['screen'] }} - - {% if row['token'] %}oui{% endif %} -
-
- - -
- - -
- -
-
-
- © Copyright Alchemy 2005-{{ "now"|date("Y") }} -
-
-
- - diff --git a/www/.htaccess b/www/.htaccess index 211328fe0b..9285d7bef0 100644 --- a/www/.htaccess +++ b/www/.htaccess @@ -47,6 +47,8 @@ RewriteRule ^robots.txt$ /index.php [L] RewriteRule ^feeds/.*$ /index.php [L] + RewriteRule ^account/.*$ /index.php [L] + RewriteRule ^developers/.*$ /index.php [L] # RewriteRule ^atom\/(cooliris)+\/?([0-9]*)\/?$ /cooliris.php?item_id=$2 [L] diff --git a/www/skins/login/css/main.css b/www/skins/login/css/main.css index 69ea5b1a36..bb5b9d748d 100644 --- a/www/skins/login/css/main.css +++ b/www/skins/login/css/main.css @@ -49,3 +49,9 @@ label { legend + .control-group { margin-top: 10px; } + +#id-main .account-menu li { + display: inline-block; + width:130px; + font-size:16px; +} \ No newline at end of file