Security: user authentication (still buging)

Service: refatoring
Translations
This commit is contained in:
Simon Vieille 2015-11-23 11:53:24 +01:00
parent 9cf3434d1a
commit ed37fbf453
16 changed files with 151 additions and 48 deletions

View file

@ -4,40 +4,47 @@ use Gist\Service\UserProvider;
use Silex\Provider\SecurityServiceProvider; use Silex\Provider\SecurityServiceProvider;
use Gist\Service\SaltGenerator; use Gist\Service\SaltGenerator;
use Silex\Provider\SessionServiceProvider; use Silex\Provider\SessionServiceProvider;
use Gist\Security\AuthentificationProvider; use Gist\Security\AuthenticationProvider;
use Gist\Security\AuthentificationListener; use Gist\Security\AuthenticationListener;
use Gist\Security\AuthenticationEntryPoint;
$app['salt_generator'] = function ($app) { $app['enable_registration'] = true;
$app['enable_login'] = true;
$app['salt_generator'] = $app->share(function($app) {
return new SaltGenerator(); return new SaltGenerator();
}; });
$app['user.provider'] = function ($app) { $app['user.provider'] = $app->share(function ($app) {
return new UserProvider( return new UserProvider(
$app['security.encoder.digest'], $app['security.encoder.digest'],
$app['salt_generator'] $app['salt_generator']
); );
}; });
$app->register(new SessionServiceProvider()); $app->register(new SessionServiceProvider());
$app['security.authentication_listener.factory.form_login'] = $app->protect(function ($name, $options) use ($app) { $app['security.authentication_listener.factory.form_login'] = $app->protect(function ($name, $options) use ($app) {
$app['security.authentication_provider.'.$name.'.form_login'] = $app->share(function ($app) { $app['security.authentication_provider.'.$name.'.form_login'] = $app->share(function ($app) {
return new AuthentificationProvider($app['user.provider']); return new AuthenticationProvider($app['user.provider']);
}); });
$app['security.authentication_listener.'.$name.'.form_login'] = $app->share(function ($app) { $app['security.authentication_listener.'.$name.'.form_login'] = $app->share(function ($app) use ($name) {
return new AuthentificationListener( return new AuthenticationListener(
$app['security.token_storage'], $app['security.token_storage'],
$app['security.authentication_manager'], $app['security.authentication_provider.'.$name.'.form_login']
$app['url_generator']
); );
}); });
$app['security.authentication.entry_point.'.$name.'.form_login'] = $app->share(function ($app) use ($name) {
return new AuthenticationEntryPoint($app['url_generator']);
});
return [ return [
'security.authentication_provider.'.$name.'.form_login', 'security.authentication_provider.'.$name.'.form_login',
'security.authentication_listener.'.$name.'.form_login', 'security.authentication_listener.'.$name.'.form_login',
null, 'security.authentication.entry_point.'.$name.'.form_login',
'pre_auth' 'pre_auth'
]; ];
}); });
@ -47,7 +54,7 @@ $app->register(
[ [
'security.firewalls' => [ 'security.firewalls' => [
'default' => [ 'default' => [
'pattern' => '^/[a-z]{2}/my', 'pattern' => '^/[a-z]{2}/',
'anonymous' => true, 'anonymous' => true,
'http' => false, 'http' => false,
'form_login' => [ 'form_login' => [

View file

@ -4,9 +4,9 @@ use Symfony\Component\Routing\Loader\YamlFileLoader;
$app['routing.file'] = 'routing.yml'; $app['routing.file'] = 'routing.yml';
$app['routing.loader'] = function ($app) { $app['routing.loader'] = $app->share(function ($app) {
return new YamlFileLoader($app['config.locator']); return new YamlFileLoader($app['config.locator']);
}; });
$app['routes'] = $app->extend('routes', function ($routes, $app) { $app['routes'] = $app->extend('routes', function ($routes, $app) {
$routes->addCollection($app['routing.loader']->load($app['routing.file'])); $routes->addCollection($app['routing.loader']->load($app['routing.file']));

View file

@ -12,10 +12,10 @@ $app->extend('twig', function ($twig, $app) {
return $twig; return $twig;
}); });
$app['geshi'] = function ($app) { $app['geshi'] = $app->share(function ($app) {
$geshi = new GeSHi(); $geshi = new GeSHi();
$geshi->enable_classes(); $geshi->enable_classes();
$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
return $geshi; return $geshi;
}; });

View file

@ -5,14 +5,14 @@ use Gist\Service\GistService;
$app['gist_path'] = $app['root_path'].'/data/git'; $app['gist_path'] = $app['root_path'].'/data/git';
$app['git_wrapper'] = function ($app) { $app['git_wrapper'] = $app->share(function ($app) {
return new GitWrapper('/usr/bin/git'); return new GitWrapper('/usr/bin/git');
}; });
$app['git_working_copy'] = function ($app) { $app['git_working_copy'] = $app->share(function ($app) {
return $app['git_wrapper']->init($app['gist_path']); return $app['git_wrapper']->init($app['gist_path']);
}; });
$app['gist'] = function ($app) { $app['gist'] = $app->share(function ($app) {
return new GistService($app['gist_path'], $app['git_wrapper'], $app['git_working_copy'], $app['geshi']); return new GistService($app['gist_path'], $app['git_wrapper'], $app['git_working_copy'], $app['geshi']);
}; });

View file

@ -2,6 +2,6 @@
use Gist\Api\Client; use Gist\Api\Client;
$app['api_client'] = function ($app) { $app['api_client'] = $app->share(function ($app) {
return new Client(['base_uri' => 'https://gist.deblan.org/']); return new Client(['base_uri' => 'https://gist.deblan.org/']);
}; });

View file

@ -35,12 +35,10 @@ _login:
defaults: {_controller: Gist\Controller\LoginController::loginAction, _locale: en} defaults: {_controller: Gist\Controller\LoginController::loginAction, _locale: en}
_login_check: _login_check:
path: /my/login_check path: /login_check
defaults: {_locale: en}
_logout: _logout:
path: /my/logout path: /logout
defaults: {_locale: en}
my: my:
path: /my path: /my

View file

@ -7,6 +7,15 @@ app:
title: 'Home' title: 'Home'
about: about:
title: 'About' title: 'About'
my:
login:
title: 'Login'
logout:
title: 'Logout'
register:
title: 'Register'
my:
title: 'Account'
gist: gist:
untitled: 'Untitled' untitled: 'Untitled'

View file

@ -7,6 +7,15 @@ app:
title: 'Accueil' title: 'Accueil'
about: about:
title: 'À propos' title: 'À propos'
my:
login:
title: 'Connexion'
logout:
title: 'Déconnexion'
register:
title: 'S''inscrire'
my:
title: 'Mon compte'
gist: gist:
untitled: 'Sans titre' untitled: 'Sans titre'

View file

@ -6,6 +6,7 @@ use Silex\Application;
use Gist\Model\Gist; use Gist\Model\Gist;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Gist\Model\GistQuery; use Gist\Model\GistQuery;
use Symfony\Component\HttpFoundation\Response;
/** /**
* Class Controller * Class Controller
@ -15,9 +16,15 @@ class Controller
{ {
protected function notFoundResponse(Application $app) protected function notFoundResponse(Application $app)
{ {
return $app['twig']->render('View/notFound.html.twig'); return new Response(
$app['twig']->render(
'View/notFound.html.twig',
[]
),
404
);
} }
protected function getViewOptions(Request $request, Application $app, $gist, $commit) protected function getViewOptions(Request $request, Application $app, $gist, $commit)
{ {
$gist = GistQuery::create()->findOneByFile($gist); $gist = GistQuery::create()->findOneByFile($gist);
@ -64,4 +71,28 @@ class Controller
return $app['gist']->getContent($gist, $commit); return $app['gist']->getContent($gist, $commit);
} }
public function getUser(Application $app)
{
$securityContext = $app['security'];
$securityToken = $securityContext->getToken();
if (!$securityToken) {
return null;
}
return $securityToken->getUser();
}
public function render($template, array $params, Application $app)
{
if (!isset($params['user'])) {
$params['user'] = $this->getUser($app);
}
return $app['twig']->render(
$template,
$params
);
}
} }

View file

@ -34,12 +34,13 @@ class EditController extends Controller
} }
} }
return $app['twig']->render( return $this->render(
'Edit/index.html.twig', 'Edit/index.html.twig',
array( array(
'gist' => isset($gist) ? $gist : null, 'gist' => isset($gist) ? $gist : null,
'form' => $form->createView(), 'form' => $form->createView(),
) ),
$app
); );
} }
@ -80,6 +81,6 @@ class EditController extends Controller
$viewOptions['form'] = $form->createView(); $viewOptions['form'] = $form->createView();
return $app['twig']->render('Edit/clone.html.twig', $viewOptions); return $this->render('Edit/clone.html.twig', $viewOptions, $app);
} }
} }

View file

@ -8,6 +8,7 @@ use Silex\Application;
use Gist\Model\User; use Gist\Model\User;
use Gist\Form\UserRegisterForm; use Gist\Form\UserRegisterForm;
use Gist\Form\UserLoginForm; use Gist\Form\UserLoginForm;
use Symfony\Component\HttpFoundation\Response;
/** /**
* Class LoginController * Class LoginController
@ -17,6 +18,10 @@ class LoginController extends Controller
{ {
public function registerAction(Request $request, Application $app) public function registerAction(Request $request, Application $app)
{ {
if (false === $app['enable_registration']) {
return new Response('', 403);
}
$user = $app['user.provider']->createUser(); $user = $app['user.provider']->createUser();
$form = new UserRegisterForm( $form = new UserRegisterForm(
@ -44,18 +49,23 @@ class LoginController extends Controller
} }
} }
return $app['twig']->render( return $this->render(
'Login/register.html.twig', 'Login/register.html.twig',
[ [
'form' => $form->createView(), 'form' => $form->createView(),
'error' => isset($error) ? $error : '', 'error' => isset($error) ? $error : '',
'success' => isset($success) ? $success : '', 'success' => isset($success) ? $success : '',
] ],
$app
); );
} }
public function loginAction(Request $request, Application $app) public function loginAction(Request $request, Application $app)
{ {
if (false === $app['enable_login']) {
return new Response('', 403);
}
$user = $app['user.provider']->createUser(); $user = $app['user.provider']->createUser();
$form = new UserLoginForm( $form = new UserLoginForm(
@ -67,17 +77,26 @@ class LoginController extends Controller
$form = $form->build()->getForm(); $form = $form->build()->getForm();
if ($request->isMethod('post')) { if ($request->query->get('error')) {
$error = $app['translator']->trans('login.login.invalid'); $error = $app['translator']->trans('login.login.invalid');
} }
return $app['twig']->render( return $this->render(
'Login/login.html.twig', 'Login/login.html.twig',
[ [
'form' => $form->createView(), 'form' => $form->createView(),
'error' => isset($error) ? $error : '', 'error' => isset($error) ? $error : '',
] ],
$app
); );
} }
public function loginCheckAction()
{
}
public function logoutAction()
{
}
} }

View file

@ -14,7 +14,8 @@ class MyController extends Controller
{ {
public function myAction(Request $request, Application $app) public function myAction(Request $request, Application $app)
{ {
return 'test'; echo '<pre>', var_dump($this->getUser($app)), '</pre>';
die;
} }
} }

View file

@ -19,7 +19,7 @@ class ViewController extends Controller
$viewOptions = $this->getViewOptions($request, $app, $gist, $commit); $viewOptions = $this->getViewOptions($request, $app, $gist, $commit);
if (is_array($viewOptions)) { if (is_array($viewOptions)) {
return $app['twig']->render('View/view.html.twig', $viewOptions); return $this->render('View/view.html.twig', $viewOptions, $app);
} else { } else {
return $this->notFoundResponse($app); return $this->notFoundResponse($app);
} }
@ -41,7 +41,7 @@ class ViewController extends Controller
$viewOptions = $this->getViewOptions($request, $app, $gist, $commit); $viewOptions = $this->getViewOptions($request, $app, $gist, $commit);
return new Response( return new Response(
$app['twig']->render('View/embedJs.html.twig', $viewOptions), $this->render('View/embedJs.html.twig', $viewOptions, $app),
200, 200,
array( array(
'Content-Type' => 'text/javascript', 'Content-Type' => 'text/javascript',
@ -102,12 +102,13 @@ class ViewController extends Controller
return $this->notFoundResponse($app); return $this->notFoundResponse($app);
} }
return $app['twig']->render( return $this->render(
'View/revisions.html.twig', 'View/revisions.html.twig',
array( array(
'gist' => $gist, 'gist' => $gist,
'history' => $history, 'history' => $history,
) ),
$app
); );
} }
} }

View file

@ -36,6 +36,33 @@
{{ 'app.menu.home.title'|trans }} {{ 'app.menu.home.title'|trans }}
</a> </a>
</li> </li>
{% if user != 'anon.' %}
<li>
<a href="{{ path('my') }}">
{{ 'app.menu.my.my.title'|trans }}
</a>
</li>
<li>
<a href="{{ path('_logout') }}">
{{ 'app.menu.my.logout.title'|trans }}
</a>
</li>
{% elseif app.enable_login %}
<li>
<a href="{{ path('_login') }}">
{{ 'app.menu.my.login.title'|trans }}
</a>
</li>
{% if app.enable_registration %}
<li>
<a href="{{ path('register') }}">
{{ 'app.menu.my.register.title'|trans }}
</a>
</li>
{% endif %}
{% endif %}
<li> <li>
<a href="https://gitlab.deblan.org/deblan/gist/src/master/README.md"> <a href="https://gitlab.deblan.org/deblan/gist/src/master/README.md">
{{ 'app.menu.about.title'|trans }} {{ 'app.menu.about.title'|trans }}

View file

@ -10,7 +10,7 @@ use InvalidArgumentException;
*/ */
class SaltGenerator class SaltGenerator
{ {
public function generate($length = 64) public function generate($length = 32)
{ {
if (!is_numeric($length)) { if (!is_numeric($length)) {
throw new InvalidArgumentException('Paramter length must be a valid integer.'); throw new InvalidArgumentException('Paramter length must be a valid integer.');

View file

@ -65,11 +65,11 @@ class UserProvider implements UserProviderInterface
public function registerUser(User $user, $password) public function registerUser(User $user, $password)
{ {
$user->setSalt($this->saltGenerator->generate(64)); $user->setSalt($this->saltGenerator->generate());
$user $user
->setRoles('ROLE_USER') ->setRoles('ROLE_USER')
->setPassword($this->encoder->encodePassword($user, $password)) ->setPassword($this->encoder->encodePassword($password, $user->getSalt()))
->save(); ->save();
return $user; return $user;
@ -78,7 +78,7 @@ class UserProvider implements UserProviderInterface
public function updateUserPassword(User $user, $password) public function updateUserPassword(User $user, $password)
{ {
$user $user
->setPassword($this->encoder->encodePassword($password)) ->setPassword($this->encoder->encodePassword($password, $user->getSalt()))
->save(); ->save();
return $user; return $user;