Controller work

This commit is contained in:
R. Eric Wheeler 2017-03-17 10:30:04 -07:00
parent a7d172a937
commit f5fd66706b
21 changed files with 739 additions and 127 deletions

2
.gitignore vendored
View File

@ -12,6 +12,4 @@ html/css/
html/images/
html/js/
lib/
t.php
test.php
variables.less

View File

@ -52,6 +52,11 @@ return PhpCsFixer\Config::create()
->ignoreDotFiles(true)
->ignoreVCS(true)
->name('*.php')
->in('src')
->in('html')
->name(__DIR__.'/app/Kernel.php')
->in([
'src',
'app',
'bin',
'html',
])
);

View File

@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- .php_cs
- php-cs-fixer
- Console
- Doctrine/DoctrineProvider/OrmProvider/DoctrineConsoleProvider
## [0.0.1] - 2017-02-07
### Added

View File

@ -30,7 +30,6 @@ use Monolog\{
Handler\StreamHandler,
Logger
};
use Sikofitt\App\Controller\DefaultController;
use Sikofitt\App\Entity\User;
use Sikofitt\App\Traits\EntityManagerTrait;
use Sikofitt\App\Traits\FlashTrait;
@ -86,7 +85,6 @@ class Kernel extends Application
use TwigTrait;
use UrlGeneratorTrait;
/**
* Kernel constructor.
*
@ -108,12 +106,11 @@ class Kernel extends Application
$this->setUpLogger();
$this->setUpMailer();
}
public function setUpRoutes(\Kernel $app)
{
$app->match('/login', DefaultController::class.'::loginAction')
->method('GET|POST');
}
/**
* @param array $values
*
@ -228,10 +225,16 @@ class Kernel extends Application
'password' => 'doughnut',
],
]);
//$j = new Doctrine\Common\Cache\FilesystemCache()
$this->register(new DoctrineOrmServiceProvider(), [
'orm.proxies_dir' => $this->getCacheDir().'/doctrine/proxies',
'orm.default_cache' => 'array',
'orm.proxies_dir' => $this->getCacheDir().'/doctrine/proxies/Doughnut/Wedding',
'orm.proxies_namespace' => 'Doughnut\Wedding',
'orm.default_cache' => [
'driver' => 'filesystem',
'path' => $this->getCacheDir().'/doctrine/cache',
],
'orm.auto_generate_proxies' => true,
'orm.strategy' => 'naming',
'orm.em.options' => [
'connection' => 'default',
'mappings' => [
@ -239,6 +242,8 @@ class Kernel extends Application
'type' => 'annotation',
'path' => $this->getBaseDir().'/src/Sikofitt/App/Entity',
'namespace' => 'Sikofitt\App\Entity',
'alias' => 'Sikofitt',
'auto_generate_proxies' => true,
'use_simple_annotation_reader' => false,
],
],
@ -327,10 +332,10 @@ class Kernel extends Application
// 'anonymous' => true
);*/
$this['protected_pages'] = function() {
$this['protected_pages'] = function () {
return [
'gallery',
'rsvp/update'
'rsvp/update',
];
};
@ -341,7 +346,6 @@ class Kernel extends Application
//->register(new SecurityServiceProvider())
;
$this->extend('form.extensions', function ($extensions) {
return $extensions;
});

View File

@ -0,0 +1,33 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ dump(app.session.get('user')) }}
{{ form_start(form) }}
<fieldset class="uk-fieldset uk-margin-small-bottom">
<legend class="uk-legend">Enter Token</legend>
</fieldset>
<div class="uk-grid-small" uk-grid>
<div class="uk-form-controls uk-form-controls-text uk-width-2-3@m">
{{ form_row(form.user_token) }}
</div>
<div class="uk-form-controls uk-width-1-3@m">
{{ form_row(form.submit) }}
</div>
</div>
<div class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<p class="uk-text-center uk-text-lead">
You can also send a new auto login link to your email.
</p>
</div>
<div class="uk-form-controls uk-width-1-1 uk-text-center">
{{ form_row(form.email) }}
</div>
<div class="uk-form-controls uk-width-1-1 uk-text-center">
{{ form_row(form.update_token) }}
</div>
</div>
<div class="form-controls uk-form-blank">
{{ form_rest(form) }}
</div>
{{ form_end(form) }}
{% endblock %}

View File

@ -0,0 +1,4 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ dump(app.session.get('user')) }}
{% endblock %}

View File

@ -0,0 +1,10 @@
{% extends 'base.html.twig' %}
{% block body %}
<h2 class="uk-text-center">You have been successfully logged out.</h2>
<p class="uk-text-center">
You can log in again by going to the <a href="{{ url('login') }}">login</a> page.
</p>
<p class="uk-text-center">
You can also login using a token by going to the <a href="{{ url('token_login') }}">token login</a> page.
</p>
{% endblock %}

1
bin/console Symbolic link
View File

@ -0,0 +1 @@
console.php

View File

@ -19,14 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use Doctrine\ORM\Tools\Console\Command\ClearCache\EntityRegionCommand;
use Doctrine\ORM\Tools\Console\Command\MappingDescribeCommand;
use Knp\Provider\ConsoleServiceProvider;
use PhpCsFixer\Console\Command\DescribeCommand;
use PhpCsFixer\Console\Command\SelfUpdateCommand;
use Sikofitt\App\Provider\DoctrineConsoleProvider;
use Symfony\Component\Console\Application;
use Symfony\Component\Yaml\Command\LintCommand;
use Symfony\Bridge\Twig\Command\DebugCommand;
use Symfony\Bridge\Twig\Command\LintCommand;
$loader = require __DIR__.'/../vendor/autoload.php';
$app = new \Kernel($loader, true);
@ -39,12 +35,20 @@ $consoleConfig = [
$app
->register(new ConsoleServiceProvider(), $consoleConfig)
->register(new DoctrineConsoleProvider());
/**
* @var Application $console
*/
$console = $app['console'];
$console->add(new Symfony\Bridge\Twig\Command\LintCommand());
$console->add(new Symfony\Bridge\Twig\Command\DebugCommand());
$console->add(new PhpCsFixer\Console\Command\FixCommand());
$console->add(new Symfony\Component\Yaml\Command\LintCommand());
$fixCommand = new \PhpCsFixer\Console\Command\FixCommand();
$fixCommand->setName('dev:fixer')->setDescription('PhpCSFixer - Fixes directories and files according to a set of rules.');
$twigLintCommand = new LintCommand();
$twigLintCommand->setTwigEnvironment($app['twig']);
$twigDebugCommand = new DebugCommand();
$twigDebugCommand->setTwigEnvironment($app['twig']);
$fixCommand->setHidden(true);
$app['console']->addCommands([
$twigDebugCommand,
$twigLintCommand,
new \Symfony\Component\Yaml\Command\LintCommand(),
$fixCommand,
]);
$app['console']->run();

View File

@ -20,8 +20,6 @@
"paragonie/cookie": "^3.1",
"paragonie/csp-builder": "^2.0",
"paragonie/sodium_compat": "^0.4.0",
"psr/http-message": "^1.0",
"psr/log": "^1.0",
"silex/silex": "^2.0",
"swiftmailer/swiftmailer": "^5.4",
"symfony/asset": "^3.2",

View File

@ -18,8 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use Sikofitt\App\Controller\DefaultController;
use Sikofitt\App\Controller\RsvpController;
use Sikofitt\App\Controller\RsvpControllerProvider;
use Sikofitt\App\Controller\UserController;
use Sikofitt\App\Middleware\CspMiddleware;
use Sikofitt\App\Middleware\HeaderMiddleware;
@ -28,25 +28,11 @@ $loader = require __DIR__.'/../vendor/autoload.php';
$app = new Kernel($loader, true);
// Controllers
// Default
$app->setUpRoutes($app);
//$app->match('/login', DefaultController::class.'loginAction')
// ->bind('login');
// RSVP Actions
$app->mount('/rsvp', new RsvpControllerProvider());
$app->mount('/user', new UserController());
$app->match('/rsvp', RsvpController::class.'::indexAction')
->method('GET|POST')
->bind('rsvp');
$app->match('/rsvp/reset', RsvpController::class.'::resetAction')
->method('GET|POST')
->bind('rsvp_password_reset');
$app->match('/rsvp/reset/{token}', RsvpController::class.'::tokenAction')
->bind('rsvp_token')
->method('GET|POST');
//->before(new MysqlAuthenticatorMiddleware());
$app->match('/rsvp/edit', RsvpController::class.'::editAction')
->method('GET|POST')
->bind('rsvp_edit');
//->before(new MysqlAuthenticatorMiddleware());
// Middleware
$app->before(new CspMiddleware(), \Kernel::EARLY_EVENT);

View File

@ -20,9 +20,6 @@
namespace Sikofitt\App\Controller;
use Sikofitt\App\Entity\User;
use Sikofitt\App\Form\UserLoginType;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
class DefaultController
@ -31,48 +28,4 @@ class DefaultController
{
return $app->render('index.html.twig', ['request' => $request]);
}
public function loginAction(Request $request, \Kernel $app)
{
if ($app->session()->has('user')) {
//return $app->redirect($app->url('rsvp_edit'));
}
$loginForm = $app->getFormFactory()->create(UserLoginType::class);
if ($request->isMethod('POST')) {
$loginForm->handleRequest($request);
if ($loginForm->isValid() && $loginForm->isSubmitted()) {
$user = $app->getEntityManager()->getRepository(User::class)->findByEmail($loginForm->get('email_username')->getData());
if (null !== $user && true === password_verify($loginForm->get('password')->getData(), $user[0]->getPassword())) {
$userSession = [
'firstName' => $user[0]->getFirstName(),
'lastName' => $user[0]->getLastName(),
'fullName' => sprintf('%s %s', $user[0]->getFirstName(), $user[0]->getLastName()),
'familySide' => $user[0]->getFamilySide(),
'email' => $user[0]->getEmail(),
'family' => $user[0]->getFamily(),
'created' => $user[0]->getCreated()->format('U'),
'updated' => $user[0]->getUpdated()->format('U'),
'guests' => $user[0]->getRsvp()->getGuests(),
];
$app->getSession()->set('user', $userSession);
$app->redirect($app->url('rsvp'));
} else {
$error = new FormError('Your password or email is incorrect.');
$error->setOrigin($loginForm);
$loginForm->get('password')->addError($error);
return $app->render('login.html.twig', ['form' => $loginForm->createView()]);
}
}
}
return $app->render('login.html.twig', ['form' => $loginForm->createView()]);
}
public function logoutAction(Request $request, \Kernel $app)
{
$app->session()->remove('user');
return $app->render('logout.html.twig');
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\App\Controller;
class RouterCollector
{
/**
* @var \Kernel
*/
private $application;
public function setApplication(\Kernel $application)
{
$this->application = $application;
return $this;
}
public function buildRoutes()
{
$this->application->match('/login', DefaultController::class.'::loginAction')
->method('GET|POST')
->bind('login');
}
}

View File

@ -45,9 +45,9 @@ class RsvpController
* @var UserRepository $userRepo
*/
$em = $app['orm.em'];
$rsvpRepo = $em->getRepository('Sikofitt\App\Entity\Rsvp');
$rsvpRepo = $em->getRepository('Sikofitt:Rsvp');
$count = (40 - $rsvpRepo->getRsvpCount());
$userRepo = $em->getRepository('Sikofitt\App\Entity\User');
$userRepo = $em->getRepository('Sikofitt:User');
$kCount = $userRepo->getKatrinaCount();
$eCount = $userRepo->getEricCount();
/**

View File

@ -0,0 +1,54 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\App\Controller;
use Pimple\Container;
use Silex\Api\ControllerProviderInterface;
use Silex\Application;
use Silex\ControllerCollection;
class RsvpControllerProvider implements ControllerProviderInterface
{
/**
* Returns routes to connect to the given application.
*
* @param Application $app An Application instance
*
* @return ControllerCollection A ControllerCollection instance
*/
public function connect(Application $app)
{
/**
* @var ControllerCollection $rsvpControllers;
*/
$rsvpControllers = $app['controllers_factory'];
$rsvpControllers
->match('/', RsvpController::class.'::indexAction')
->method('GET|POST')
->bind('rsvp');
return $rsvpControllers;
}
public function register(Container $pimple)
{
}
}

View File

@ -0,0 +1,234 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\App\Controller;
use Sikofitt\App\Form\UserLoginType;
use Sikofitt\App\Form\UserTokenType;
use Sikofitt\Security\TokenGenerator;
use Silex\Api\ControllerProviderInterface;
use Silex\Application;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* Class UserController.
*/
class UserController implements ControllerProviderInterface
{
public function connect(Application $app)
{
/**
* @var ControllerCollection $userControllers
*/
$userControllers = $app['controllers_factory'];
$userControllers->match('/', __CLASS__.'::indexAction')
->method('GET')
->bind('user_index');
$userControllers->match('/login', __CLASS__.'::loginAction')
->method('GET|POST')
->bind('login');
$userControllers->get('/logout', __CLASS__.'::logoutAction')
->bind('logout');
$userControllers->match('/login/token/{token}', __CLASS__.'::tokenLoginAction')
->method('GET|POST')
->bind('token_login')
->value('token', null);
$userControllers->match('/reset', __CLASS__.'::resetAction')
->method('GET|POST')
->bind('user_reset');
$userControllers->match('/reset/{token}', __CLASS__.'::tokenAction')
->bind('user_reset_token')
->method('GET|POST');
//->before(new MysqlAuthenticatorMiddleware());
$userControllers->match('/edit', __CLASS__.'::editAction')
->method('GET|POST')
->bind('user_edit');
return $userControllers;
}
public function logoutAction(\Kernel $app)
{
if (true === $app->session()->has('user')) {
$app->session()->remove('user');
}
return $app->render('user/logout.html.twig');
}
public function tokenLoginAction(Request $request, \Kernel $app, string $token = null)
{
if (null === $token) {
$tokenForm = $app->getFormFactory()->create(UserTokenType::class);
if ($request->isMethod('POST')) {
$tokenForm->handleRequest($request);
if ($tokenForm->isValid() && $tokenForm->isSubmitted()) {
if ($tokenForm->get('update_token')->isClicked()) {
if (null !== $tokenForm->get('email')->getData()) {
return $this->updateAndSendTokenLoginLink($app,
$tokenForm);
} else {
$tokenForm->get('email')
->addError(new FormError('Email address is a required field to send a new login link.'));
return $app->render('form/token.html.twig',
['form' => $tokenForm->createView()]);
}
} else {
$userToken = $tokenForm->get('user_token')->getData();
$user = $app->getEntityManager()
->getRepository('Sikofitt:User')
->getUserByUserToken($userToken);
if (null === $user) {
$tokenForm->get('user_token')
->addError(new FormError('Token is invalid.'));
} else {
$app->session()->set('user', $user);
}
return $app->render('form/token.html.twig',
['form' => $tokenForm->createView()]);
}
} else {
return $app->render('form/token.html.twig',
['form' => $tokenForm->createView()]);
}
}
return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]);
} else {
// Token has been included.
$app->session()->remove('user');
$tokenForm = $app->getFormFactory()->create(UserTokenType::class);
//$user = $app->getEntityManager()->getRepository('Sikofitt:User')->getUserByUserToken($token);
$user = $app->getEntityManager()->getRepository('Sikofitt:User')->findOneBy(['userToken' => $token]);
if (null !== $user) {
$app->session()->set('user', $user);
return $app->render('user/index.html.twig');
} else {
return new StreamedResponse(function () use ($app, $tokenForm, $token) {
$tokenForm->get('user_token')->setData($token);
$tokenForm->get('user_token')->addError(new FormError('Invalid token.'));
print $app->renderView('form/token.html.twig', ['form' => $tokenForm->createView()]);
});
}
}
}
public function indexAction(Request $request, \Kernel $app)
{
if ($app->session()->has('user')) {
return new JsonResponse(
[
'request' => $request->request->all(),
'server' => $request->server->all(),
'headers' => $request->headers->all(),
'session' => $app->getSession()->get('user'),
'token' => (string) new TokenGenerator(),
]
);
}
}
public function loginAction(Request $request, \Kernel $app)
{
if ($app->session()->has('user')) {
//return $app->redirect($app->url('rsvp_edit'));
}
$loginForm = $app->getFormFactory()->create(UserLoginType::class);
if ($request->isMethod('POST')) {
$loginForm->handleRequest($request);
if ($loginForm->isValid() && $loginForm->isSubmitted()) {
$user = $app->getEntityManager()->getRepository(User::class)->findByEmail($loginForm->get('email_username')->getData());
if (null !== $user && true === password_verify($loginForm->get('password')->getData(), $user[0]->getPassword())) {
$userSession = [
'firstName' => $user[0]->getFirstName(),
'lastName' => $user[0]->getLastName(),
'fullName' => sprintf('%s %s', $user[0]->getFirstName(), $user[0]->getLastName()),
'familySide' => $user[0]->getFamilySide(),
'email' => $user[0]->getEmail(),
'family' => $user[0]->getFamily(),
'created' => $user[0]->getCreated()->format('U'),
'updated' => $user[0]->getUpdated()->format('U'),
'guests' => $user[0]->getRsvp()->getGuests(),
];
$app->getSession()->set('user', $userSession);
$app->redirect($app->url('rsvp'));
} else {
$error = new FormError('Your password or email is incorrect.');
$error->setOrigin($loginForm);
$loginForm->get('password')->addError($error);
return $app->render('login.html.twig', ['form' => $loginForm->createView()]);
}
}
}
return $app->render('login.html.twig', ['form' => $loginForm->createView()]);
}
public function resetAction(Request $request, \Kernel $app)
{
}
public function tokenAction(Request $request, \Kernel $app)
{
}
public function editAction(Request $request, \Kernel $app)
{
}
private function tokenFormGenerator(\Kernel $app)
{
return;
}
private function updateAndSendTokenLoginLink(\Kernel $app, \Symfony\Component\Form\FormInterface $tokenForm)
{
$email = $tokenForm->get('email')->getData();
$user = $app->getEntityManager()
->getRepository('Sikofitt:User')
->findByEmail($email);
if (null === $user) {
$tokenForm->get('email')->addError(new FormError('Sorry we couldn\'t find your email address.'));
return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]);
}
$newToken = $app->getEntityManager()
->getRepository('Sikofitt:User')
->setUserToken($email);
if (false !== $newToken) {
$user->setUserToken($newToken);
$app->session()->set('user', $user);
return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]);
}
$tokenForm->get('email')->addError(new FormError('An Unknown error occured. Please try again.'));
return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]);
}
}

View File

@ -0,0 +1,59 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\App\Controller;
use Silex\Api\ControllerProviderInterface;
use Silex\Application;
use Silex\ControllerCollection;
class UserControllerProvider implements ControllerProviderInterface
{
/**
* Returns routes to connect to the given application.
*
* @param Application $app An Application instance
*
* @return ControllerCollection A ControllerCollection instance
*/
public function connect(Application $app)
{
/**
* @var ControllerCollection $userControllers
*/
$userControllers = $app['controllers_factory'];
$app->match('/user', UserController::class.'::indexAction')
->method('GET')
->bind('user_index');
$app->match('/user/reset', UserController::class.'::resetAction')
->method('GET|POST')
->bind('user_reset');
$app->match('/user/reset/{token}', UserController::class.'::tokenAction')
->bind('user_reset_token')
->method('GET|POST');
//->before(new MysqlAuthenticatorMiddleware());
$app->match('/user/edit', UserController::class.'::editAction')
->method('GET|POST')
->bind('user_edit');
return $userControllers;
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Length;
class UserTokenType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user_token', TextType::class, [
'attr' => [
'class' => 'uk-input uk-form-large',
'placehoder' => 'Token',
],
'required' => false,
'label_attr' => [
'class' => 'uk-form-label uk-hidden',
],
'constraints' => [
new Length([
'min' => 64,
'max' => 64,
'minMessage' => 'Token should be exactly {{ limit }} characters.',
'maxMessage' => 'Token should be exactly {{ limit }} characters.',
'exactMessage' => 'Token should be exactly {{ limit }} characters.',
]),
],
])->add('submit', SubmitType::class, [
'attr' => [
'class' => 'uk-button uk-button-large uk-button-primary',
],
'label' => 'Login',
])->add('email', EmailType::class, [
'required' => false,
'constraints' => [
new Email([
'strict' => true,
'checkMX' => true,
'checkHost' => true,
]),
],
'attr' => [
'class' => 'uk-input uk-form-large uk-text-center',
'placeholder' => 'Email Address',
],
'label_attr' => [
'class' => 'uk-form-label',
],
])->add('update_token', SubmitType::class, [
'attr' => [
'class' => 'uk-button uk-button-large uk-button-primary',
],
'label' => 'Send New Login Link',
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('attr', ['class' => 'uk-form uk-align-center']);
}
}

View File

@ -20,12 +20,12 @@
namespace Sikofitt\App\Provider;
use Doctrine\DBAL\Tools\Console\Command\{
ImportCommand,
ReservedWordsCommand,
RunSqlCommand
};
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
use Doctrine\ORM\Tools\Console\Command\{
ClearCache\EntityRegionCommand, ClearCache\MetadataCommand,
ClearCache\QueryCommand, ClearCache\ResultCommand,
@ -52,6 +52,8 @@ class DoctrineConsoleProvider implements ServiceProviderInterface
* It should not get services.
*
* @param Container $pimple A container instance
*
* @throws \LogicException
*/
public function register(Container $pimple)
{
@ -61,24 +63,26 @@ class DoctrineConsoleProvider implements ServiceProviderInterface
if (false === isset($pimple['db.options'])) {
throw new \LogicException('You must enable the DoctrineServiceProvider to use the DoctrineConsoleProvider.');
}
if(false === isset($pimple['orm.em'])) {
if (false === isset($pimple['orm.em'])) {
throw new \LogicException('You must enable the Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider to use the DoctrineConsoleProvider.');
}
$console = $pimple['console'];
$console->setHelperSet(new HelperSet(array(
'em' => new EntityManagerHelper($pimple['orm.em'])
)));
$console->setHelperSet(new HelperSet([
'em' => new EntityManagerHelper($pimple['orm.em']),
'db' => new ConnectionHelper($pimple['db']),
]));
$updateCommand = new UpdateCommand();
$updateCommand->setName('orm:schema:update');
$schemaUpdateCommand = (new UpdateCommand())
->setName('orm:schema:update');
$schemaValidateCommand = (new ValidateSchemaCommand())
->setName('orm:schema:validate')
->setAliases(['orm:validate']);
->setAliases(['validate']);
$schemaDropCommand = (new DropCommand())
->setName('orm:schema:drop');
$schemaCreateCommand = (new CreateCommand())
->setName('orm:schema:create');
$queryCommand = new QueryCommand();
$console->addCommands([
new ConvertDoctrine1SchemaCommand(),
@ -99,8 +103,8 @@ class DoctrineConsoleProvider implements ServiceProviderInterface
new ResultCommand(),
$schemaCreateCommand,
$schemaDropCommand,
$schemaUpdateCommand,
$schemaValidateCommand,
]);
}
}

View File

@ -23,7 +23,7 @@ namespace Sikofitt\App\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Sikofitt\App\Entity\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Sikofitt\Security\TokenGenerator;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Validation;
@ -34,17 +34,25 @@ use Symfony\Component\Validator\Validation;
*/
class UserRepository extends EntityRepository
{
/**
* @param string $email
*
* @return null|User
*/
public function findByEmail(string $email)
{
return $this->findBy(['email' => $email]);
/*return $this->createQueryBuilder('u')
->select('u')
return $this->createQueryBuilder('u')
->select(['u', 'r'])
->leftJoin('u.rsvp', 'r', 'WITH', 'u.rsvp = r.id')
->where('u.email = :email')
->setParameter('email', $email)
->getQuery()
->getOneOrNullResult(Query::HYDRATE_OBJECT);*/
->getOneOrNullResult(Query::HYDRATE_OBJECT);
}
/**
* @return int
*/
public function getKatrinaCount()
{
return $this->createQueryBuilder('u')
@ -53,9 +61,12 @@ class UserRepository extends EntityRepository
->where('u.familySide = :side')
->setParameter('side', User::KATRINA_SIDE)
->getQuery()
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR);
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR) ?? 0;
}
/**
* @return int
*/
public function getEricCount()
{
return $this->createQueryBuilder('u')
@ -64,9 +75,14 @@ class UserRepository extends EntityRepository
->where('u.familySide = :side')
->setParameter('side', User::ERIC_SIDE)
->getQuery()
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR);
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR) ?? 0;
}
/**
* @param string $email
*
* @return mixed|\Symfony\Component\Validator\ConstraintViolationListInterface
*/
public function getEmail(string $email)
{
$validator = Validation::createValidator();
@ -90,35 +106,90 @@ class UserRepository extends EntityRepository
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR);
}
public function getUserByToken(string $token)
/**
* @param string $resetToken
*
* @return User|null
*/
public function getUserByResetToken(string $resetToken)
{
return $this->createQueryBuilder('u')
->select(['u'])
->where('u.token = :token')
->setParameter('token', $token)
->select(['u', 'r'])
->leftJoin('u.rsvp', 'r', 'WITH', 'u.rsvp = r.id')
->where('u.resetToken = :resetToken')
->setParameter('resetToken', $resetToken)
->getQuery()
->getOneOrNullResult();
->getOneOrNullResult(Query::HYDRATE_OBJECT);
}
/**
* @param string $userToken
*
* @return User|null
*/
public function getUserByUserToken(string $userToken)
{
return $this->createQueryBuilder('u')
->select(['u', 'r'])
->leftJoin('u.rsvp', 'r', 'WITH', 'u.rsvp = r.id')
->where('u.userToken = :userToken')
->setParameter('userToken', $userToken)
->getQuery()
->getOneOrNullResult(Query::HYDRATE_OBJECT);
}
/**
* Sets or updates user's user login token.
*
* @param string $email
*
* @return bool|string
*/
public function setUserToken(string $email)
{
$userToken = (string) new TokenGenerator();
$result = (bool) $this->createQueryBuilder('u')
->update()
->set('u.userToken', ':userToken')
->setParameter('userToken', $userToken)
->where('u.email = :email')
->setParameter('email', $email)
->getQuery()
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR);
return true === $result ? $userToken : false;
}
/**
* Sets or updates user's reset password token.
*
* @param string $email
*
* @return bool
*/
public function setResetToken(string $email)
{
$bytes = \ParagonIE_Sodium_Compat::randombytes_buf(22);
$blake = \ParagonIE_Sodium_Compat::crypto_generichash($bytes);
$token = \ParagonIE_Sodium_Core_BLAKE2b::bin2hex($blake);
$resetToken = (string) new TokenGenerator();
return (bool) $this->createQueryBuilder('u')
->update()
->set('u.token', ':token')
->setParameter('token', $token)
->set('u.resetToken', ':resetToken')
->setParameter('resetToken', $resetToken)
->where('u.email = :email')
->setParameter('email', $email)
->getQuery()
->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR);
}
public function updatePassword(UserInterface $user)
/**
* Updates a user.
*
* @param User|\Symfony\Component\Security\Core\User\UserInterface $user
*/
public function destoryUserResetToken(User $user)
{
$user->setToken(null);
$user->setResetToken(null);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}

View File

@ -0,0 +1,60 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Security;
use ParagonIE_Sodium_Compat as SodiumCompat;
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
/**
* Class TokenGenerator.
*/
class TokenGenerator implements TokenGeneratorInterface
{
public function __toString()
{
return $this->generateToken();
}
/**
* Generates a reset or user token.
*
* @return string The generated token
*/
public function generateToken()
{
$randomBytes = substr(
SodiumCompat::randombytes_buf(512),
random_int(SodiumCompat::CRYPTO_GENERICHASH_BYTES, 512),
SodiumCompat::CRYPTO_GENERICHASH_BYTES_MAX
);
$rawToken = SodiumCompat::crypto_generichash(
$randomBytes,
SodiumCompat::randombytes_buf(
SodiumCompat::CRYPTO_GENERICHASH_BYTES_MAX
),
32
);
$token = SodiumCompat::bin2hex($rawToken);
return $token;
}
}