From fcb1fba5c2fdb12c9f4041bd334aaced6f302d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 29 Sep 2015 14:31:52 +0200 Subject: [PATCH 01/13] * public registration * remove WSSE implementation * add oAuth2 implementation --- app/AppKernel.php | 1 + app/config/config.yml | 14 ++ app/config/config_prod.yml | 5 - app/config/routing.yml | 6 + app/config/security.yml | 21 +- app/config/services.yml | 5 - composer.json | 3 +- composer.lock | 158 ++++++++++-- .../Controller/WallabagRestController.php | 51 +--- .../Security/Factory/WsseFactory.php | 40 --- .../WallabagApiExtension.php | 3 - src/Wallabag/ApiBundle/Entity/AccessToken.php | 31 +++ src/Wallabag/ApiBundle/Entity/AuthCode.php | 31 +++ src/Wallabag/ApiBundle/Entity/Client.php | 25 ++ .../ApiBundle/Entity/RefreshToken.php | 31 +++ .../ApiBundle/Resources/config/services.yml | 12 - .../Authentication/Provider/WsseProvider.php | 79 ------ .../Authentication/Token/WsseUserToken.php | 24 -- .../Security/Firewall/WsseListener.php | 62 ----- .../Tests/AbstractControllerTest.php | 46 ++++ .../Controller/WallabagRestControllerTest.php | 238 +++++------------- src/Wallabag/ApiBundle/WallabagApiBundle.php | 9 - .../Controller/ConfigController.php | 15 +- .../DataFixtures/ORM/LoadUserData.php | 5 +- src/Wallabag/CoreBundle/Entity/User.php | 22 +- .../EventListener/AuthenticationListener.php | 44 ++++ .../CoreBundle/Form/Type/NewUserType.php | 3 +- .../CoreBundle/Form/Type/RegistrationType.php | 24 ++ .../CoreBundle/Resources/config/services.yml | 11 + .../views/themes/baggy/Config/index.html.twig | 16 +- .../themes/material/Config/index.html.twig | 19 +- .../themes/material/Security/login.html.twig | 1 + .../Tests/Controller/ConfigControllerTest.php | 24 +- 33 files changed, 551 insertions(+), 528 deletions(-) delete mode 100644 src/Wallabag/ApiBundle/DependencyInjection/Security/Factory/WsseFactory.php create mode 100644 src/Wallabag/ApiBundle/Entity/AccessToken.php create mode 100644 src/Wallabag/ApiBundle/Entity/AuthCode.php create mode 100644 src/Wallabag/ApiBundle/Entity/Client.php create mode 100644 src/Wallabag/ApiBundle/Entity/RefreshToken.php delete mode 100644 src/Wallabag/ApiBundle/Resources/config/services.yml delete mode 100644 src/Wallabag/ApiBundle/Security/Authentication/Provider/WsseProvider.php delete mode 100644 src/Wallabag/ApiBundle/Security/Authentication/Token/WsseUserToken.php delete mode 100644 src/Wallabag/ApiBundle/Security/Firewall/WsseListener.php create mode 100644 src/Wallabag/ApiBundle/Tests/AbstractControllerTest.php create mode 100644 src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php create mode 100644 src/Wallabag/CoreBundle/Form/Type/RegistrationType.php diff --git a/app/AppKernel.php b/app/AppKernel.php index 08e14b8f7..6f8c3a6d6 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -26,6 +26,7 @@ class AppKernel extends Kernel new Wallabag\ApiBundle\WallabagApiBundle(), new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(), new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(), + new FOS\OAuthServerBundle\FOSOAuthServerBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { diff --git a/app/config/config.yml b/app/config/config.yml index f623ab237..adf68d6ca 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -157,3 +157,17 @@ fos_user: db_driver: orm firewall_name: main user_class: Wallabag\CoreBundle\Entity\User + registration: + form: + type: wallabag_user_registration + confirmation: + enabled: true + +fos_oauth_server: + db_driver: orm + client_class: Wallabag\ApiBundle\Entity\Client + access_token_class: Wallabag\ApiBundle\Entity\AccessToken + refresh_token_class: Wallabag\ApiBundle\Entity\RefreshToken + auth_code_class: Wallabag\ApiBundle\Entity\AuthCode + service: + user_provider: fos_user.user_manager diff --git a/app/config/config_prod.yml b/app/config/config_prod.yml index c45f0fa66..342837a03 100644 --- a/app/config/config_prod.yml +++ b/app/config/config_prod.yml @@ -17,11 +17,6 @@ monolog: type: fingers_crossed action_level: error handler: nested - wsse: - type: stream - path: %kernel.logs_dir%/%kernel.environment%.wsse.log - level: error - channels: [wsse] nested: type: stream path: "%kernel.logs_dir%/%kernel.environment%.log" diff --git a/app/config/routing.yml b/app/config/routing.yml index e8bf08a57..dabb48fa7 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -30,3 +30,9 @@ homepage: defaults: { _controller: WallabagCoreBundle:Entry:showUnread, page : 1 } requirements: page: \d+ + +fos_user: + resource: "@FOSUserBundle/Resources/config/routing/all.xml" + +fos_oauth_server_token: + resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" diff --git a/app/config/security.yml b/app/config/security.yml index 988466562..6533a430d 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -1,9 +1,6 @@ security: encoders: - Wallabag\CoreBundle\Entity\User: - algorithm: sha1 - encode_as_base64: false - iterations: 1 + FOS\UserBundle\Model\UserInterface: sha512 role_hierarchy: ROLE_ADMIN: ROLE_USER @@ -18,11 +15,15 @@ security: # the main part of the security, where you can set up firewalls # for specific sections of your app firewalls: - wsse_secured: - pattern: /api/.* - wsse: true - stateless: true - anonymous: true + oauth_token: + pattern: ^/oauth/v2/token + security: false + api: + pattern: /api/.* + fos_oauth: true + stateless: true + anonymous: false + login_firewall: pattern: ^/login$ anonymous: ~ @@ -45,9 +46,9 @@ security: target: / access_control: - - { path: ^/api/salt, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/forgot-password, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: /(unread|starred|archive).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/, roles: ROLE_USER } diff --git a/app/config/services.yml b/app/config/services.yml index 965bc3195..ff6a582bb 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -1,9 +1,4 @@ -# Learn more about services, parameters and containers at -# http://symfony.com/doc/current/book/service_container.html parameters: - security.authentication.provider.dao.class: Wallabag\CoreBundle\Security\Authentication\Provider\WallabagAuthenticationProvider - security.encoder.digest.class: Wallabag\CoreBundle\Security\Authentication\Encoder\WallabagPasswordEncoder - security.validator.user_password.class: Wallabag\CoreBundle\Security\Validator\WallabagUserPasswordValidator lexik_form_filter.get_filter.doctrine_orm.class: Wallabag\CoreBundle\Event\Subscriber\CustomDoctrineORMSubscriber services: diff --git a/composer.json b/composer.json index babe9356d..22cb277c4 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,8 @@ "pagerfanta/pagerfanta": "~1.0.3", "lexik/form-filter-bundle": "~4.0", "j0k3r/graby": "~1.0", - "friendsofsymfony/user-bundle": "dev-master" + "friendsofsymfony/user-bundle": "dev-master", + "friendsofsymfony/oauth-server-bundle": "^1.4@dev" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "~2.2.0", diff --git a/composer.lock b/composer.lock index 370d8ddd9..606c3678d 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "350d05d95be50b6d93e8a046f784e00c", + "hash": "7c1f2c88df608eb6e1b4bc7c5ed24acc", "packages": [ { "name": "doctrine/annotations", @@ -858,6 +858,129 @@ ], "time": "2014-05-20 12:10:12" }, + { + "name": "friendsofsymfony/oauth-server-bundle", + "version": "1.4.2", + "target-dir": "FOS/OAuthServerBundle", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/FOSOAuthServerBundle.git", + "reference": "9e15c229eff547443d686445d629e9356ab0672e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSOAuthServerBundle/zipball/9e15c229eff547443d686445d629e9356ab0672e", + "reference": "9e15c229eff547443d686445d629e9356ab0672e", + "shasum": "" + }, + "require": { + "friendsofsymfony/oauth2-php": "~1.1.0", + "php": ">=5.3.3", + "symfony/framework-bundle": "~2.1", + "symfony/security-bundle": "~2.1" + }, + "require-dev": { + "doctrine/doctrine-bundle": "~1.0", + "doctrine/mongodb-odm": "1.0.*@dev", + "doctrine/orm": ">=2.2,<2.5-dev", + "symfony/class-loader": "~2.1", + "symfony/yaml": "~2.1", + "willdurand/propel-typehintable-behavior": "1.0.*" + }, + "suggest": { + "doctrine/doctrine-bundle": "*", + "doctrine/mongodb-odm-bundle": "*", + "propel/propel-bundle": "If you want to use Propel with Symfony2, then you will have to install the PropelBundle", + "willdurand/propel-typehintable-behavior": "The Typehintable behavior is useful to add type hints on generated methods, to be compliant with interfaces" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-0": { + "FOS\\OAuthServerBundle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arnaud Le Blanc", + "email": "arnaud.lb@gmail.com" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/contributors" + } + ], + "description": "Symfony2 OAuth Server Bundle", + "homepage": "http://friendsofsymfony.github.com", + "keywords": [ + "oauth", + "oauth2", + "server" + ], + "time": "2014-10-31 13:44:14" + }, + { + "name": "friendsofsymfony/oauth2-php", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/oauth2-php.git", + "reference": "23e76537c4a02e666ab4ba5abe67a69a886a0310" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/oauth2-php/zipball/23e76537c4a02e666ab4ba5abe67a69a886a0310", + "reference": "23e76537c4a02e666ab4ba5abe67a69a886a0310", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "symfony/http-foundation": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "OAuth2\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arnaud Le Blanc", + "email": "arnaud.lb@gmail.com" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/FriendsOfSymfony/oauth2-php/contributors" + } + ], + "description": "OAuth2 library", + "homepage": "https://github.com/FriendsOfSymfony/oauth2-php", + "keywords": [ + "oauth", + "oauth2" + ], + "time": "2014-11-03 10:21:20" + }, { "name": "friendsofsymfony/rest-bundle", "version": "1.7.1", @@ -2787,12 +2910,12 @@ "version": "v2.7.0", "source": { "type": "git", - "url": "https://github.com/symfony/AsseticBundle.git", + "url": "https://github.com/symfony/assetic-bundle.git", "reference": "3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/AsseticBundle/zipball/3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5", + "url": "https://api.github.com/repos/symfony/assetic-bundle/zipball/3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5", "reference": "3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5", "shasum": "" }, @@ -2857,12 +2980,12 @@ "version": "v2.7.1", "source": { "type": "git", - "url": "https://github.com/symfony/MonologBundle.git", + "url": "https://github.com/symfony/monolog-bundle.git", "reference": "9320b6863404c70ebe111e9040dab96f251de7ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/MonologBundle/zipball/9320b6863404c70ebe111e9040dab96f251de7ac", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/9320b6863404c70ebe111e9040dab96f251de7ac", "reference": "9320b6863404c70ebe111e9040dab96f251de7ac", "shasum": "" }, @@ -2916,12 +3039,12 @@ "version": "v2.3.8", "source": { "type": "git", - "url": "https://github.com/symfony/SwiftmailerBundle.git", + "url": "https://github.com/symfony/swiftmailer-bundle.git", "reference": "970b13d01871207e81d17b17ddda025e7e21e797" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/SwiftmailerBundle/zipball/970b13d01871207e81d17b17ddda025e7e21e797", + "url": "https://api.github.com/repos/symfony/swiftmailer-bundle/zipball/970b13d01871207e81d17b17ddda025e7e21e797", "reference": "970b13d01871207e81d17b17ddda025e7e21e797", "shasum": "" }, @@ -2970,20 +3093,20 @@ }, { "name": "symfony/symfony", - "version": "v2.7.5", + "version": "v2.7.4", "source": { "type": "git", "url": "https://github.com/symfony/symfony.git", - "reference": "619528a274647cffc1792063c3ea04c4fa8266a0" + "reference": "1fdf23fe28876844b887b0e1935c9adda43ee645" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/symfony/zipball/619528a274647cffc1792063c3ea04c4fa8266a0", - "reference": "619528a274647cffc1792063c3ea04c4fa8266a0", + "url": "https://api.github.com/repos/symfony/symfony/zipball/1fdf23fe28876844b887b0e1935c9adda43ee645", + "reference": "1fdf23fe28876844b887b0e1935c9adda43ee645", "shasum": "" }, "require": { - "doctrine/common": "~2.4", + "doctrine/common": "~2.3", "php": ">=5.3.9", "psr/log": "~1.0", "twig/twig": "~1.20|~2.0" @@ -3036,9 +3159,9 @@ }, "require-dev": { "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.4", + "doctrine/dbal": "~2.2", "doctrine/doctrine-bundle": "~1.2", - "doctrine/orm": "~2.4,>=2.4.5", + "doctrine/orm": "~2.2,>=2.2.3", "egulias/email-validator": "~1.2", "ircmaxell/password-compat": "~1.0", "monolog/monolog": "~1.11", @@ -3088,7 +3211,7 @@ "keywords": [ "framework" ], - "time": "2015-09-25 11:16:52" + "time": "2015-09-08 14:26:39" }, { "name": "tecnickcom/tcpdf", @@ -4488,7 +4611,8 @@ "aliases": [], "minimum-stability": "dev", "stability-flags": { - "friendsofsymfony/user-bundle": 20 + "friendsofsymfony/user-bundle": 20, + "friendsofsymfony/oauth-server-bundle": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index 349229f38..284dbb25f 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php @@ -2,8 +2,8 @@ namespace Wallabag\ApiBundle\Controller; +use FOS\RestBundle\Controller\FOSRestController; use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Wallabag\CoreBundle\Entity\Entry; @@ -11,7 +11,7 @@ use Wallabag\CoreBundle\Entity\Tag; use Hateoas\Configuration\Route; use Hateoas\Representation\Factory\PagerfantaFactory; -class WallabagRestController extends Controller +class WallabagRestController extends FOSRestController { /** * @param Entry $entry @@ -38,31 +38,6 @@ class WallabagRestController extends Controller } } - /** - * Retrieve salt for a giver user. - * - * @ApiDoc( - * parameters={ - * {"name"="username", "dataType"="string", "required"=true, "description"="username"} - * } - * ) - * - * @return array - */ - public function getSaltAction($username) - { - $user = $this - ->getDoctrine() - ->getRepository('WallabagCoreBundle:User') - ->findOneByUsername($username); - - if (is_null($user)) { - throw $this->createNotFoundException(); - } - - return array($user->getSalt() ?: null); - } - /** * Retrieve all entries. It could be filtered by many options. * @@ -122,7 +97,7 @@ class WallabagRestController extends Controller */ public function getEntryAction(Entry $entry) { - $this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($entry->getUser()->getId()); $json = $this->get('serializer')->serialize($entry, 'json'); @@ -184,7 +159,7 @@ class WallabagRestController extends Controller */ public function patchEntriesAction(Entry $entry, Request $request) { - $this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($entry->getUser()->getId()); $title = $request->request->get('title'); $isArchived = $request->request->get('is_archived'); @@ -228,7 +203,7 @@ class WallabagRestController extends Controller */ public function deleteEntriesAction(Entry $entry) { - $this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($entry->getUser()->getId()); $em = $this->getDoctrine()->getManager(); $em->remove($entry); @@ -250,7 +225,7 @@ class WallabagRestController extends Controller */ public function getEntriesTagsAction(Entry $entry) { - $this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($entry->getUser()->getId()); $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); @@ -271,7 +246,7 @@ class WallabagRestController extends Controller */ public function postEntriesTagsAction(Request $request, Entry $entry) { - $this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($entry->getUser()->getId()); $tags = $request->request->get('tags', ''); if (!empty($tags)) { @@ -299,7 +274,7 @@ class WallabagRestController extends Controller */ public function deleteEntriesTagsAction(Entry $entry, Tag $tag) { - $this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($entry->getUser()->getId()); $entry->removeTag($tag); $em = $this->getDoctrine()->getManager(); @@ -334,7 +309,7 @@ class WallabagRestController extends Controller */ public function deleteTagAction(Tag $tag) { - $this->validateUserAccess($tag->getUser()->getId(), $this->getUser()->getId()); + $this->validateUserAccess($tag->getUser()->getId()); $em = $this->getDoctrine()->getManager(); $em->remove($tag); @@ -350,12 +325,12 @@ class WallabagRestController extends Controller * If not, throw exception. It means a user try to access information from an other user. * * @param int $requestUserId User id from the requested source - * @param int $currentUserId User id from the retrieved source */ - private function validateUserAccess($requestUserId, $currentUserId) + private function validateUserAccess($requestUserId) { - if ($requestUserId != $currentUserId) { - throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$requestUserId.', logged user id: '.$currentUserId); + $user = $this->get('security.context')->getToken()->getUser(); + if ($requestUserId != $user->getId()) { + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$requestUserId.', logged user id: '.$user->getId()); } } diff --git a/src/Wallabag/ApiBundle/DependencyInjection/Security/Factory/WsseFactory.php b/src/Wallabag/ApiBundle/DependencyInjection/Security/Factory/WsseFactory.php deleted file mode 100644 index 402eb8692..000000000 --- a/src/Wallabag/ApiBundle/DependencyInjection/Security/Factory/WsseFactory.php +++ /dev/null @@ -1,40 +0,0 @@ -setDefinition($providerId, new DefinitionDecorator('wsse.security.authentication.provider')) - ->replaceArgument(0, new Reference($userProvider)) - ; - - $listenerId = 'security.authentication.listener.wsse.'.$id; - $listener = $container->setDefinition($listenerId, new DefinitionDecorator('wsse.security.authentication.listener')); - - return array($providerId, $listenerId, $defaultEntryPoint); - } - - public function getPosition() - { - return 'pre_auth'; - } - - public function getKey() - { - return 'wsse'; - } - - public function addConfiguration(NodeDefinition $node) - { - } -} diff --git a/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php b/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php index c5cc204e0..a147e7ef7 100644 --- a/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php +++ b/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php @@ -13,9 +13,6 @@ class WallabagApiExtension extends Extension { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); - - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('services.yml'); } public function getAlias() diff --git a/src/Wallabag/ApiBundle/Entity/AccessToken.php b/src/Wallabag/ApiBundle/Entity/AccessToken.php new file mode 100644 index 000000000..d6cf0af5d --- /dev/null +++ b/src/Wallabag/ApiBundle/Entity/AccessToken.php @@ -0,0 +1,31 @@ +userProvider = $userProvider; - $this->cacheDir = $cacheDir; - - // If cache directory does not exist we create it - if (!is_dir($this->cacheDir)) { - mkdir($this->cacheDir, 0777, true); - } - } - - public function authenticate(TokenInterface $token) - { - $user = $this->userProvider->loadUserByUsername($token->getUsername()); - - if (!$user) { - throw new AuthenticationException('Bad credentials. Did you forgot your username?'); - } - - if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) { - $authenticatedToken = new WsseUserToken($user->getRoles()); - $authenticatedToken->setUser($user); - - return $authenticatedToken; - } - - throw new AuthenticationException('The WSSE authentication failed.'); - } - - protected function validateDigest($digest, $nonce, $created, $secret) - { - // Check created time is not in the future - if (strtotime($created) > time()) { - throw new AuthenticationException('Back to the future...'); - } - - // Expire timestamp after 5 minutes - if (time() - strtotime($created) > 300) { - throw new AuthenticationException('Too late for this timestamp... Watch your watch.'); - } - - // Validate nonce is unique within 5 minutes - if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time()) { - throw new NonceExpiredException('Previously used nonce detected'); - } - - file_put_contents($this->cacheDir.'/'.$nonce, time()); - - // Validate Secret - $expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true)); - - if ($digest !== $expected) { - throw new AuthenticationException('Bad credentials ! Digest is not as expected.'); - } - - return $digest === $expected; - } - - public function supports(TokenInterface $token) - { - return $token instanceof WsseUserToken; - } -} diff --git a/src/Wallabag/ApiBundle/Security/Authentication/Token/WsseUserToken.php b/src/Wallabag/ApiBundle/Security/Authentication/Token/WsseUserToken.php deleted file mode 100644 index e6d30224b..000000000 --- a/src/Wallabag/ApiBundle/Security/Authentication/Token/WsseUserToken.php +++ /dev/null @@ -1,24 +0,0 @@ -setAuthenticated(count($roles) > 0); - } - - public function getCredentials() - { - return ''; - } -} diff --git a/src/Wallabag/ApiBundle/Security/Firewall/WsseListener.php b/src/Wallabag/ApiBundle/Security/Firewall/WsseListener.php deleted file mode 100644 index 2fcbe014e..000000000 --- a/src/Wallabag/ApiBundle/Security/Firewall/WsseListener.php +++ /dev/null @@ -1,62 +0,0 @@ -securityContext = $securityContext; - $this->authenticationManager = $authenticationManager; - $this->logger = $logger; - } - - public function handle(GetResponseEvent $event) - { - $request = $event->getRequest(); - - $wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/'; - if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) { - return; - } - - $token = new WsseUserToken(); - $token->setUser($matches[1]); - - $token->digest = $matches[2]; - $token->nonce = $matches[3]; - $token->created = $matches[4]; - - try { - $authToken = $this->authenticationManager->authenticate($token); - - $this->securityContext->setToken($authToken); - - return; - } catch (AuthenticationException $failed) { - $failedMessage = 'WSSE Login failed for '.$token->getUsername().'. Why ? '.$failed->getMessage(); - $this->logger->err($failedMessage); - - // Deny authentication with a '403 Forbidden' HTTP response - $response = new Response(); - $response->setStatusCode(403); - $response->setContent($failedMessage); - $event->setResponse($response); - - return; - } - } -} diff --git a/src/Wallabag/ApiBundle/Tests/AbstractControllerTest.php b/src/Wallabag/ApiBundle/Tests/AbstractControllerTest.php new file mode 100644 index 000000000..119889b38 --- /dev/null +++ b/src/Wallabag/ApiBundle/Tests/AbstractControllerTest.php @@ -0,0 +1,46 @@ +client = $this->createAuthorizedClient(); + } + + /** + * @return Client + */ + protected function createAuthorizedClient() + { + $client = static::createClient(); + $container = $client->getContainer(); + + $session = $container->get('session'); + /** @var $userManager \FOS\UserBundle\Doctrine\UserManager */ + $userManager = $container->get('fos_user.user_manager'); + /** @var $loginManager \FOS\UserBundle\Security\LoginManager */ + $loginManager = $container->get('fos_user.security.login_manager'); + $firewallName = $container->getParameter('fos_user.firewall_name'); + + $user = $userManager->findUserBy(array('username' => 'admin')); + $loginManager->loginUser($firewallName, $user); + + // save the login token into the session and put it in a cookie + $container->get('session')->set('_security_'.$firewallName, + serialize($container->get('security.context')->getToken())); + $container->get('session')->save(); + $client->getCookieJar()->set(new Cookie($session->getName(), $session->getId())); + + return $client; + } +} diff --git a/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php index 7ae54b576..bc7ef4895 100644 --- a/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php @@ -2,99 +2,15 @@ namespace Wallabag\ApiBundle\Tests\Controller; -use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Wallabag\ApiBundle\Tests\AbstractControllerTest; -class WallabagRestControllerTest extends WebTestCase +class WallabagRestControllerTest extends AbstractControllerTest { protected static $salt; - /** - * Grab the salt once and store it to be available for all tests. - */ - public static function setUpBeforeClass() - { - $client = self::createClient(); - - $user = $client->getContainer() - ->get('doctrine.orm.entity_manager') - ->getRepository('WallabagCoreBundle:User') - ->findOneByUsername('admin'); - - self::$salt = $user->getSalt(); - } - - /** - * Generate HTTP headers for authenticate user on API. - * - * @param string $username - * @param string $password - * - * @return array - */ - private function generateHeaders($username, $password) - { - $encryptedPassword = sha1($password.$username.self::$salt); - $nonce = substr(md5(uniqid('nonce_', true)), 0, 16); - - $now = new \DateTime('now', new \DateTimeZone('UTC')); - $created = (string) $now->format('Y-m-d\TH:i:s\Z'); - $digest = base64_encode(sha1(base64_decode($nonce).$created.$encryptedPassword, true)); - - return array( - 'HTTP_AUTHORIZATION' => 'Authorization profile="UsernameToken"', - 'HTTP_x-wsse' => 'X-WSSE: UsernameToken Username="'.$username.'", PasswordDigest="'.$digest.'", Nonce="'.$nonce.'", Created="'.$created.'"', - ); - } - - public function testGetSalt() - { - $client = $this->createClient(); - $client->request('GET', '/api/salts/admin.json'); - - $user = $client->getContainer() - ->get('doctrine.orm.entity_manager') - ->getRepository('WallabagCoreBundle:User') - ->findOneByUsername('admin'); - - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); - - $this->assertArrayHasKey(0, $content); - $this->assertEquals($user->getSalt(), $content[0]); - - $client->request('GET', '/api/salts/notfound.json'); - $this->assertEquals(404, $client->getResponse()->getStatusCode()); - } - - public function testWithBadHeaders() - { - $client = $this->createClient(); - - $entry = $client->getContainer() - ->get('doctrine.orm.entity_manager') - ->getRepository('WallabagCoreBundle:Entry') - ->findOneByIsArchived(false); - - if (!$entry) { - $this->markTestSkipped('No content found in db.'); - } - - $badHeaders = array( - 'HTTP_AUTHORIZATION' => 'Authorization profile="UsernameToken"', - 'HTTP_x-wsse' => 'X-WSSE: UsernameToken Username="admin", PasswordDigest="Wr0ngDig3st", Nonce="n0Nc3", Created="2015-01-01T13:37:00Z"', - ); - - $client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $badHeaders); - $this->assertEquals(403, $client->getResponse()->getStatusCode()); - } - public function testGetOneEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->findOneBy(array('user' => 1, 'isArchived' => false)); @@ -103,18 +19,17 @@ class WallabagRestControllerTest extends WebTestCase $this->markTestSkipped('No content found in db.'); } - $client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers); + $this->client->request('GET', '/api/entries/'.$entry->getId().'.json'); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertEquals($entry->getTitle(), $content['title']); $this->assertEquals($entry->getUrl(), $content['url']); $this->assertCount(count($entry->getTags()), $content['tags']); $this->assertTrue( - $client->getResponse()->headers->contains( + $this->client->getResponse()->headers->contains( 'Content-Type', 'application/json' ) @@ -123,10 +38,7 @@ class WallabagRestControllerTest extends WebTestCase public function testGetOneEntryWrongUser() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->findOneBy(array('user' => 2, 'isArchived' => false)); @@ -135,21 +47,18 @@ class WallabagRestControllerTest extends WebTestCase $this->markTestSkipped('No content found in db.'); } - $client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers); + $this->client->request('GET', '/api/entries/'.$entry->getId().'.json'); - $this->assertEquals(403, $client->getResponse()->getStatusCode()); + $this->assertEquals(403, $this->client->getResponse()->getStatusCode()); } public function testGetEntries() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); + $this->client->request('GET', '/api/entries'); - $client->request('GET', '/api/entries', array(), array(), $headers); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertGreaterThanOrEqual(1, count($content)); $this->assertNotEmpty($content['_embedded']['items']); @@ -158,7 +67,7 @@ class WallabagRestControllerTest extends WebTestCase $this->assertGreaterThanOrEqual(1, $content['pages']); $this->assertTrue( - $client->getResponse()->headers->contains( + $this->client->getResponse()->headers->contains( 'Content-Type', 'application/json' ) @@ -167,14 +76,11 @@ class WallabagRestControllerTest extends WebTestCase public function testGetStarredEntries() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); + $this->client->request('GET', '/api/entries', array('star' => 1, 'sort' => 'updated')); - $client->request('GET', '/api/entries', array('star' => 1, 'sort' => 'updated'), array(), $headers); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertGreaterThanOrEqual(1, count($content)); $this->assertNotEmpty($content['_embedded']['items']); @@ -183,7 +89,7 @@ class WallabagRestControllerTest extends WebTestCase $this->assertGreaterThanOrEqual(1, $content['pages']); $this->assertTrue( - $client->getResponse()->headers->contains( + $this->client->getResponse()->headers->contains( 'Content-Type', 'application/json' ) @@ -192,14 +98,11 @@ class WallabagRestControllerTest extends WebTestCase public function testGetArchiveEntries() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); + $this->client->request('GET', '/api/entries', array('archive' => 1)); - $client->request('GET', '/api/entries', array('archive' => 1), array(), $headers); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertGreaterThanOrEqual(1, count($content)); $this->assertNotEmpty($content['_embedded']['items']); @@ -208,7 +111,7 @@ class WallabagRestControllerTest extends WebTestCase $this->assertGreaterThanOrEqual(1, $content['pages']); $this->assertTrue( - $client->getResponse()->headers->contains( + $this->client->getResponse()->headers->contains( 'Content-Type', 'application/json' ) @@ -217,10 +120,7 @@ class WallabagRestControllerTest extends WebTestCase public function testDeleteEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->findOneByUser(1); @@ -229,36 +129,31 @@ class WallabagRestControllerTest extends WebTestCase $this->markTestSkipped('No content found in db.'); } - $client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers); + $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertEquals($entry->getTitle(), $content['title']); $this->assertEquals($entry->getUrl(), $content['url']); // We'll try to delete this entry again - $headers = $this->generateHeaders('admin', 'mypassword'); + $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json'); - $client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers); - - $this->assertEquals(404, $client->getResponse()->getStatusCode()); + $this->assertEquals(404, $this->client->getResponse()->getStatusCode()); } public function testPostEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $client->request('POST', '/api/entries.json', array( + $this->client->request('POST', '/api/entries.json', array( 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', 'tags' => 'google', - ), array(), $headers); + )); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertGreaterThan(0, $content['id']); $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']); @@ -269,10 +164,7 @@ class WallabagRestControllerTest extends WebTestCase public function testPatchEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->findOneByUser(1); @@ -284,16 +176,16 @@ class WallabagRestControllerTest extends WebTestCase // hydrate the tags relations $nbTags = count($entry->getTags()); - $client->request('PATCH', '/api/entries/'.$entry->getId().'.json', array( + $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', array( 'title' => 'New awesome title', 'tags' => 'new tag '.uniqid(), 'star' => true, 'archive' => false, - ), array(), $headers); + )); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertEquals($entry->getId(), $content['id']); $this->assertEquals($entry->getUrl(), $content['url']); @@ -303,10 +195,7 @@ class WallabagRestControllerTest extends WebTestCase public function testGetTagsEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->findOneWithTags(1); @@ -322,17 +211,14 @@ class WallabagRestControllerTest extends WebTestCase $tags[] = array('id' => $tag->getId(), 'label' => $tag->getLabel()); } - $client->request('GET', '/api/entries/'.$entry->getId().'/tags', array(), array(), $headers); + $this->client->request('GET', '/api/entries/'.$entry->getId().'/tags'); - $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $client->getResponse()->getContent()); + $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent()); } public function testPostTagsOnEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->findOneByUser(1); @@ -345,16 +231,16 @@ class WallabagRestControllerTest extends WebTestCase $newTags = 'tag1,tag2,tag3'; - $client->request('POST', '/api/entries/'.$entry->getId().'/tags', array('tags' => $newTags), array(), $headers); + $this->client->request('POST', '/api/entries/'.$entry->getId().'/tags', array('tags' => $newTags)); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertArrayHasKey('tags', $content); $this->assertEquals($nbTags + 3, count($content['tags'])); - $entryDB = $client->getContainer() + $entryDB = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') ->find($entry->getId()); @@ -369,15 +255,13 @@ class WallabagRestControllerTest extends WebTestCase } } - public function testDeleteOneTagEntrie() + public function testDeleteOneTagEntry() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); - - $entry = $client->getContainer() + $entry = $this->client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') - ->findOneByUser(1); + ->findOneWithTags(1); + $entry = $entry[0]; if (!$entry) { $this->markTestSkipped('No content found in db.'); @@ -387,11 +271,11 @@ class WallabagRestControllerTest extends WebTestCase $nbTags = count($entry->getTags()); $tag = $entry->getTags()[0]; - $client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json', array(), array(), $headers); + $this->client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertArrayHasKey('tags', $content); $this->assertEquals($nbTags - 1, count($content['tags'])); @@ -399,14 +283,11 @@ class WallabagRestControllerTest extends WebTestCase public function testGetUserTags() { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); + $this->client->request('GET', '/api/tags.json'); - $client->request('GET', '/api/tags.json', array(), array(), $headers); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertGreaterThan(0, $content); $this->assertArrayHasKey('id', $content[0]); @@ -420,14 +301,11 @@ class WallabagRestControllerTest extends WebTestCase */ public function testDeleteUserTag($tag) { - $client = $this->createClient(); - $headers = $this->generateHeaders('admin', 'mypassword'); + $this->client->request('DELETE', '/api/tags/'.$tag['id'].'.json'); - $client->request('DELETE', '/api/tags/'.$tag['id'].'.json', array(), array(), $headers); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode($this->client->getResponse()->getContent(), true); $this->assertArrayHasKey('label', $content); $this->assertEquals($tag['label'], $content['label']); diff --git a/src/Wallabag/ApiBundle/WallabagApiBundle.php b/src/Wallabag/ApiBundle/WallabagApiBundle.php index 2484f2779..19d887aba 100644 --- a/src/Wallabag/ApiBundle/WallabagApiBundle.php +++ b/src/Wallabag/ApiBundle/WallabagApiBundle.php @@ -3,16 +3,7 @@ namespace Wallabag\ApiBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; -use Wallabag\ApiBundle\DependencyInjection\Security\Factory\WsseFactory; -use Symfony\Component\DependencyInjection\ContainerBuilder; class WallabagApiBundle extends Bundle { - public function build(ContainerBuilder $container) - { - parent::build($container); - - $extension = $container->getExtension('security'); - $extension->addSecurityListenerFactory(new WsseFactory()); - } } diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 5affdee89..27c323b71 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php @@ -25,6 +25,7 @@ class ConfigController extends Controller { $em = $this->getDoctrine()->getManager(); $config = $this->getConfig(); + $userManager = $this->container->get('fos_user.user_manager'); $user = $this->getUser(); // handle basic config detail (this form is defined as a service) @@ -52,9 +53,8 @@ class ConfigController extends Controller $pwdForm->handleRequest($request); if ($pwdForm->isValid()) { - $user->setPassword($pwdForm->get('new_password')->getData()); - $em->persist($user); - $em->flush(); + $user->setPlainPassword($pwdForm->get('new_password')->getData()); + $userManager->updateUser($user, true); $this->get('session')->getFlashBag()->add( 'notice', @@ -69,8 +69,7 @@ class ConfigController extends Controller $userForm->handleRequest($request); if ($userForm->isValid()) { - $em->persist($user); - $em->flush(); + $userManager->updateUser($user, true); $this->get('session')->getFlashBag()->add( 'notice', @@ -97,14 +96,14 @@ class ConfigController extends Controller } // handle adding new user - $newUser = new User(); + $newUser = $userManager->createUser(); // enable created user by default $newUser->setEnabled(true); $newUserForm = $this->createForm(new NewUserType(), $newUser, array('validation_groups' => array('Profile'))); $newUserForm->handleRequest($request); - if ($newUserForm->isValid()) { - $em->persist($newUser); + if ($newUserForm->isValid() && $this->get('security.authorization_checker')->isGranted('ROLE_SUPER_ADMIN')) { + $userManager->updateUser($newUser, true); $config = new Config($newUser); $config->setTheme($this->container->getParameter('theme')); diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php index 4ef53329c..811451da7 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php @@ -18,8 +18,9 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface $userAdmin->setName('Big boss'); $userAdmin->setEmail('bigboss@wallabag.org'); $userAdmin->setUsername('admin'); - $userAdmin->setPassword('mypassword'); + $userAdmin->setPlainPassword('mypassword'); $userAdmin->setEnabled(true); + $userAdmin->addRole('ROLE_SUPER_ADMIN'); $manager->persist($userAdmin); @@ -29,7 +30,7 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface $bobUser->setName('Bobby'); $bobUser->setEmail('bobby@wallabag.org'); $bobUser->setUsername('bob'); - $bobUser->setPassword('mypassword'); + $bobUser->setPlainPassword('mypassword'); $bobUser->setEnabled(true); $manager->persist($bobUser); diff --git a/src/Wallabag/CoreBundle/Entity/User.php b/src/Wallabag/CoreBundle/Entity/User.php index a60023523..ae2902a32 100644 --- a/src/Wallabag/CoreBundle/Entity/User.php +++ b/src/Wallabag/CoreBundle/Entity/User.php @@ -6,7 +6,6 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Core\User\AdvancedUserInterface; use JMS\Serializer\Annotation\ExclusionPolicy; use JMS\Serializer\Annotation\Expose; use FOS\UserBundle\Model\User as BaseUser; @@ -22,7 +21,7 @@ use FOS\UserBundle\Model\User as BaseUser; * @UniqueEntity("email") * @UniqueEntity("username") */ -class User extends BaseUser implements AdvancedUserInterface, \Serializable +class User extends BaseUser { /** * @var int @@ -75,6 +74,7 @@ class User extends BaseUser implements AdvancedUserInterface, \Serializable parent::__construct(); $this->entries = new ArrayCollection(); $this->tags = new ArrayCollection(); + $this->roles = array('ROLE_USER'); } /** @@ -90,24 +90,6 @@ class User extends BaseUser implements AdvancedUserInterface, \Serializable $this->updatedAt = new \DateTime(); } - /** - * Set password. - * - * @param string $password - * - * @return User - */ - public function setPassword($password) - { - if (!$password && 0 === strlen($password)) { - return; - } - - $this->password = sha1($password.$this->getUsername().$this->getSalt()); - - return $this; - } - /** * Set name. * diff --git a/src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php b/src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php new file mode 100644 index 000000000..7c2826ecd --- /dev/null +++ b/src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php @@ -0,0 +1,44 @@ +container = $container; + $this->em = $em; + } + + public static function getSubscribedEvents() + { + return array( + FOSUserEvents::REGISTRATION_CONFIRMED => 'authenticate', + ); + } + + public function authenticate(FilterUserResponseEvent $event, $eventName = null, EventDispatcherInterface $eventDispatcher = null) + { + if (!$event->getUser()->isEnabled()) { + return; + } + + $config = new Config($event->getUser()); + $config->setTheme($this->container->getParameter('theme')); + $config->setItemsPerPage($this->container->getParameter('items_on_page')); + $config->setRssLimit($this->container->getParameter('rss_limit')); + $config->setLanguage($this->container->getParameter('language')); + $this->em->persist($config); + $this->em->flush(); + } +} diff --git a/src/Wallabag/CoreBundle/Form/Type/NewUserType.php b/src/Wallabag/CoreBundle/Form/Type/NewUserType.php index 985cb55b2..ea7bb7aef 100644 --- a/src/Wallabag/CoreBundle/Form/Type/NewUserType.php +++ b/src/Wallabag/CoreBundle/Form/Type/NewUserType.php @@ -13,7 +13,8 @@ class NewUserType extends AbstractType { $builder ->add('username', 'text', array('required' => true)) - ->add('password', 'password', array( + ->add('plainPassword', 'repeated', array( + 'type' => 'password', 'constraints' => array( new Constraints\Length(array( 'min' => 8, diff --git a/src/Wallabag/CoreBundle/Form/Type/RegistrationType.php b/src/Wallabag/CoreBundle/Form/Type/RegistrationType.php new file mode 100644 index 000000000..47d4f341c --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/RegistrationType.php @@ -0,0 +1,24 @@ +add('name'); + } + + public function getParent() + { + return 'fos_user_registration'; + } + + public function getName() + { + return 'wallabag_user_registration'; + } +} diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 3beb5d0ef..96ea482ae 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -13,6 +13,11 @@ services: tags: - { name: form.type, alias: config } + wallabag_core.form.registration: + class: Wallabag\CoreBundle\Form\Type\RegistrationType + tags: + - { name: form.type, alias: wallabag_user_registration } + wallabag_core.form.type.forgot_password: class: Wallabag\CoreBundle\Form\Type\ForgotPasswordType arguments: @@ -40,3 +45,9 @@ services: class: Wallabag\CoreBundle\Helper\ContentProxy arguments: - @wallabag_core.graby + + wallabag_core.registration_confirmed: + class: Wallabag\CoreBundle\EventListener\AuthenticationListener + arguments: [@service_container, @doctrine.orm.entity_manager] + tags: + - { name: kernel.event_subscriber } diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig index c90bb2e3b..64305b163 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig @@ -135,6 +135,7 @@ {{ form_rest(form.pwd) }} + {% if is_granted('ROLE_SUPER_ADMIN') %}

{% trans %}Add a user{% endtrans %}

@@ -150,9 +151,17 @@
- {{ form_label(form.new_user.password) }} - {{ form_errors(form.new_user.password) }} - {{ form_widget(form.new_user.password) }} + {{ form_label(form.new_user.plainPassword.first) }} + {{ form_errors(form.new_user.plainPassword.first) }} + {{ form_widget(form.new_user.plainPassword.first) }} +
+
+ +
+
+ {{ form_label(form.new_user.plainPassword.second) }} + {{ form_errors(form.new_user.plainPassword.second) }} + {{ form_widget(form.new_user.plainPassword.second) }}
@@ -165,5 +174,6 @@ {{ form_rest(form.new_user) }} + {% endif %}
{% endblock %} diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig index 0ff21f223..0d8e9f241 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig @@ -15,7 +15,9 @@
  • {% trans %}RSS{% endtrans %}
  • {% trans %}User information{% endtrans %}
  • {% trans %}Password{% endtrans %}
  • + {% if is_granted('ROLE_SUPER_ADMIN') %}
  • {% trans %}Add a user{% endtrans %}
  • + {% endif %} @@ -175,7 +177,7 @@ - + {% if is_granted('ROLE_SUPER_ADMIN') %}
    {{ form_errors(form.new_user) }} @@ -190,9 +192,17 @@
    - {{ form_label(form.new_user.password) }} - {{ form_errors(form.new_user.password) }} - {{ form_widget(form.new_user.password) }} + {{ form_label(form.new_user.plainPassword.first) }} + {{ form_errors(form.new_user.plainPassword.first) }} + {{ form_widget(form.new_user.plainPassword.first) }} +
    +
    + +
    +
    + {{ form_label(form.new_user.plainPassword.second) }} + {{ form_errors(form.new_user.plainPassword.second) }} + {{ form_widget(form.new_user.plainPassword.second) }}
    @@ -211,6 +221,7 @@
    + {% endif %} diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig index 4eb6d2b8c..10f380fe3 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig @@ -49,6 +49,7 @@ {% trans %}Login{% endtrans %} + {% trans %}Register{% endtrans %} diff --git a/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php index 3407fc5e0..708a07b16 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php @@ -258,7 +258,8 @@ class ConfigControllerTest extends WallabagCoreTestCase array( array( 'new_user[username]' => '', - 'new_user[password]' => '', + 'new_user[plainPassword][first]' => '', + 'new_user[plainPassword][second]' => '', 'new_user[email]' => '', ), 'Please enter a username', @@ -266,7 +267,8 @@ class ConfigControllerTest extends WallabagCoreTestCase array( array( 'new_user[username]' => 'a', - 'new_user[password]' => 'mypassword', + 'new_user[plainPassword][first]' => 'mypassword', + 'new_user[plainPassword][second]' => 'mypassword', 'new_user[email]' => '', ), 'The username is too short', @@ -274,7 +276,8 @@ class ConfigControllerTest extends WallabagCoreTestCase array( array( 'new_user[username]' => 'wallace', - 'new_user[password]' => 'mypassword', + 'new_user[plainPassword][first]' => 'mypassword', + 'new_user[plainPassword][second]' => 'mypassword', 'new_user[email]' => 'test', ), 'The email is not valid', @@ -282,11 +285,21 @@ class ConfigControllerTest extends WallabagCoreTestCase array( array( 'new_user[username]' => 'admin', - 'new_user[password]' => 'wallacewallace', + 'new_user[plainPassword][first]' => 'wallacewallace', + 'new_user[plainPassword][second]' => 'wallacewallace', 'new_user[email]' => 'wallace@wallace.me', ), 'The username is already used', ), + array( + array( + 'new_user[username]' => 'wallace', + 'new_user[plainPassword][first]' => 'mypassword1', + 'new_user[plainPassword][second]' => 'mypassword2', + 'new_user[email]' => 'wallace@wallace.me', + ), + 'This value is not valid', + ), ); } @@ -325,7 +338,8 @@ class ConfigControllerTest extends WallabagCoreTestCase $data = array( 'new_user[username]' => 'wallace', - 'new_user[password]' => 'wallace1', + 'new_user[plainPassword][first]' => 'wallace1', + 'new_user[plainPassword][second]' => 'wallace1', 'new_user[email]' => 'wallace@wallace.me', ); From cd1298d6dfc8a811f3808a85bf73f7686c29a0a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 29 Sep 2015 14:52:46 +0200 Subject: [PATCH 02/13] allow API documentation for anonymous --- app/config/config.yml | 4 +++- app/config/security.yml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/config/config.yml b/app/config/config.yml index adf68d6ca..3c63ded3e 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -110,7 +110,9 @@ fos_rest: routing_loader: default_format: json -nelmio_api_doc: ~ +nelmio_api_doc: + sandbox: + enabled: false nelmio_cors: defaults: diff --git a/app/config/security.yml b/app/config/security.yml index 6533a430d..79a07c48e 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -22,7 +22,7 @@ security: pattern: /api/.* fos_oauth: true stateless: true - anonymous: false + anonymous: true login_firewall: pattern: ^/login$ From 772732531ea1d0f9831cc5f29e11b6b11fd088f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 29 Sep 2015 14:57:46 +0200 Subject: [PATCH 03/13] check authentication on each API route --- .../Controller/WallabagRestController.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index 284dbb25f..1fee56ad1 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php @@ -38,6 +38,13 @@ class WallabagRestController extends FOSRestController } } + private function validateAuthentication() + { + if (false === $this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) { + throw new AccessDeniedException(); + } + } + /** * Retrieve all entries. It could be filtered by many options. * @@ -57,6 +64,8 @@ class WallabagRestController extends FOSRestController */ public function getEntriesAction(Request $request) { + $this->validateAuthentication(); + $isArchived = $request->query->get('archive'); $isStarred = $request->query->get('star'); $sort = $request->query->get('sort', 'created'); @@ -97,6 +106,7 @@ class WallabagRestController extends FOSRestController */ public function getEntryAction(Entry $entry) { + $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); $json = $this->get('serializer')->serialize($entry, 'json'); @@ -119,6 +129,8 @@ class WallabagRestController extends FOSRestController */ public function postEntriesAction(Request $request) { + $this->validateAuthentication(); + $url = $request->request->get('url'); $entry = $this->get('wallabag_core.content_proxy')->updateEntry( @@ -159,6 +171,7 @@ class WallabagRestController extends FOSRestController */ public function patchEntriesAction(Entry $entry, Request $request) { + $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); $title = $request->request->get('title'); @@ -203,6 +216,7 @@ class WallabagRestController extends FOSRestController */ public function deleteEntriesAction(Entry $entry) { + $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); $em = $this->getDoctrine()->getManager(); @@ -225,6 +239,7 @@ class WallabagRestController extends FOSRestController */ public function getEntriesTagsAction(Entry $entry) { + $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); @@ -246,6 +261,7 @@ class WallabagRestController extends FOSRestController */ public function postEntriesTagsAction(Request $request, Entry $entry) { + $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); $tags = $request->request->get('tags', ''); @@ -274,6 +290,7 @@ class WallabagRestController extends FOSRestController */ public function deleteEntriesTagsAction(Entry $entry, Tag $tag) { + $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); $entry->removeTag($tag); @@ -293,6 +310,7 @@ class WallabagRestController extends FOSRestController */ public function getTagsAction() { + $this->validateAuthentication(); $json = $this->get('serializer')->serialize($this->getUser()->getTags(), 'json'); return $this->renderJsonResponse($json); @@ -309,6 +327,7 @@ class WallabagRestController extends FOSRestController */ public function deleteTagAction(Tag $tag) { + $this->validateAuthentication(); $this->validateUserAccess($tag->getUser()->getId()); $em = $this->getDoctrine()->getManager(); From 359b3f43cc42aa593cdba7dc8e1d6fa121cc3f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 29 Sep 2015 17:05:17 +0200 Subject: [PATCH 04/13] * rename AuthenticationListener * add tests --- ....php => RegistrationConfirmedListener.php} | 2 +- .../CoreBundle/Resources/config/services.yml | 2 +- .../themes/baggy/Security/login.html.twig | 1 + .../Controller/SecurityControllerTest.php | 93 +++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) rename src/Wallabag/CoreBundle/EventListener/{AuthenticationListener.php => RegistrationConfirmedListener.php} (94%) diff --git a/src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php b/src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php similarity index 94% rename from src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php rename to src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php index 7c2826ecd..bcc84923b 100644 --- a/src/Wallabag/CoreBundle/EventListener/AuthenticationListener.php +++ b/src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php @@ -9,7 +9,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use FOS\UserBundle\Event\FilterUserResponseEvent; use Wallabag\CoreBundle\Entity\Config; -class AuthenticationListener implements EventSubscriberInterface +class RegistrationConfirmedListener implements EventSubscriberInterface { private $em; private $container; diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 96ea482ae..f22472607 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -47,7 +47,7 @@ services: - @wallabag_core.graby wallabag_core.registration_confirmed: - class: Wallabag\CoreBundle\EventListener\AuthenticationListener + class: Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener arguments: [@service_container, @doctrine.orm.entity_manager] tags: - { name: kernel.event_subscriber } diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Security/login.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Security/login.html.twig index 5437d20c4..9a59dfc60 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Security/login.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Security/login.html.twig @@ -32,6 +32,7 @@ diff --git a/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php index 759ef01b0..78b4952e4 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php @@ -8,6 +8,99 @@ use Wallabag\CoreBundle\Tests\WallabagCoreTestCase; class SecurityControllerTest extends WallabagCoreTestCase { + public function testRegister() + { + $client = $this->getClient(); + + $crawler = $client->request('GET', '/register/'); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertContains('Register', $client->getResponse()->getContent()); + } + + public function dataForCreateAccountFailed() + { + return array( + array( + array( + 'fos_user_registration_form[email]' => '', + 'fos_user_registration_form[username]' => 'newuser', + 'fos_user_registration_form[plainPassword][first]' => 'mypassword', + 'fos_user_registration_form[plainPassword][second]' => 'mypassword', + ), + 'Please enter an email', + ), + array( + array( + 'fos_user_registration_form[email]' => 'newuser@wallabag.org', + 'fos_user_registration_form[username]' => 'admin', + 'fos_user_registration_form[plainPassword][first]' => 'mypassword', + 'fos_user_registration_form[plainPassword][second]' => 'mypassword', + ), + 'The username is already used', + ), + array( + array( + 'fos_user_registration_form[email]' => 'newuser@wallabag.org', + 'fos_user_registration_form[username]' => 'newuser', + 'fos_user_registration_form[plainPassword][first]' => 'mypassword1', + 'fos_user_registration_form[plainPassword][second]' => 'mypassword2', + ), + 'The entered passwords don't match', + ), + ); + } + + /** + * @dataProvider dataForCreateAccountFailed + */ + public function testCreateAccountFailed($data, $expectedMessage) + { + $client = $this->getClient(); + + $crawler = $client->request('GET', '/register/'); + + $form = $crawler->filter('input[type=submit]')->form(); + + $client->submit($form, $data); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertContains($expectedMessage, $client->getResponse()->getContent()); + } + + public function dataForCreateAccountSuccess() + { + return array( + array( + array( + 'fos_user_registration_form[email]' => 'newuser@wallabag.org', + 'fos_user_registration_form[username]' => 'newuser', + 'fos_user_registration_form[plainPassword][first]' => 'mypassword', + 'fos_user_registration_form[plainPassword][second]' => 'mypassword', + ), + ) + ); + } + + /** + * @dataProvider dataForCreateAccountSuccess + */ + public function testCreateAccountSuccess($data) + { + $client = $this->getClient(); + + $crawler = $client->request('GET', '/register/'); + + $form = $crawler->filter('input[type=submit]')->form(); + + $client->submit($form, $data); + $this->assertEquals(302, $client->getResponse()->getStatusCode()); + + $crawler = $client->followRedirect(); + + $this->assertContains('The user has been created successfully', $client->getResponse()->getContent()); + } + public function testLogin() { $client = $this->getClient(); From 2c13918acc3c46120bbef5e6746f3c6dc27be5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 29 Sep 2015 18:11:57 +0200 Subject: [PATCH 05/13] add test for confirmed registration --- .../WallabagApiExtension.php | 2 -- .../Controller/SecurityControllerTest.php | 27 ++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php b/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php index a147e7ef7..cde43aedb 100644 --- a/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php +++ b/src/Wallabag/ApiBundle/DependencyInjection/WallabagApiExtension.php @@ -3,9 +3,7 @@ namespace Wallabag\ApiBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\DependencyInjection\Loader; class WallabagApiExtension extends Extension { diff --git a/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php index 78b4952e4..7af9d5c45 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php @@ -78,7 +78,7 @@ class SecurityControllerTest extends WallabagCoreTestCase 'fos_user_registration_form[plainPassword][first]' => 'mypassword', 'fos_user_registration_form[plainPassword][second]' => 'mypassword', ), - ) + ), ); } @@ -101,6 +101,31 @@ class SecurityControllerTest extends WallabagCoreTestCase $this->assertContains('The user has been created successfully', $client->getResponse()->getContent()); } + public function testRegistrationConfirmation() + { + $client = $this->getClient(); + $client->followRedirects(); + + $user = $client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:User') + ->findOneByUsername('newuser'); + + $this->assertNull($user->getConfig()); + + $client->request('GET', '/register/confirm/b4dT0k3n'); + $this->assertEquals(404, $client->getResponse()->getStatusCode()); + + $crawler = $client->request('GET', '/register/confirm/'.$user->getConfirmationToken()); + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + + $user = $client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:User') + ->findOneByUsername('newuser'); + $this->assertNotNull($user->getConfig()); + } + public function testLogin() { $client = $this->getClient(); From 772d8c4b93adc36baefda93ec37007e4a85321de Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Thu, 1 Oct 2015 22:25:23 +0200 Subject: [PATCH 06/13] Add test on RegistrationConfirmedListener And PLEASE @nicosomb, NEVER EVER inject the whole container inside a service. --- .../RegistrationConfirmedListener.php | 24 +++-- .../CoreBundle/Resources/config/services.yml | 10 +- .../RegistrationConfirmedListenerTest.php | 92 +++++++++++++++++++ 3 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 src/Wallabag/CoreBundle/Tests/EventListener/RegistrationConfirmedListenerTest.php diff --git a/src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php b/src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php index bcc84923b..68c25f1f5 100644 --- a/src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php +++ b/src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php @@ -2,22 +2,28 @@ namespace Wallabag\CoreBundle\EventListener; -use FOS\UserBundle\FOSUserEvents; -use Symfony\Component\DependencyInjection\Container; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Doctrine\ORM\EntityManager; use FOS\UserBundle\Event\FilterUserResponseEvent; +use FOS\UserBundle\FOSUserEvents; use Wallabag\CoreBundle\Entity\Config; class RegistrationConfirmedListener implements EventSubscriberInterface { private $em; - private $container; + private $theme; + private $itemsOnPage; + private $rssLimit; + private $language; - public function __construct(Container $container, $em) + public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language) { - $this->container = $container; $this->em = $em; + $this->theme = $theme; + $this->itemsOnPage = $itemsOnPage; + $this->rssLimit = $rssLimit; + $this->language = $language; } public static function getSubscribedEvents() @@ -34,10 +40,10 @@ class RegistrationConfirmedListener implements EventSubscriberInterface } $config = new Config($event->getUser()); - $config->setTheme($this->container->getParameter('theme')); - $config->setItemsPerPage($this->container->getParameter('items_on_page')); - $config->setRssLimit($this->container->getParameter('rss_limit')); - $config->setLanguage($this->container->getParameter('language')); + $config->setTheme($this->theme); + $config->setItemsPerPage($this->itemsOnPage); + $config->setRssLimit($this->rssLimit); + $config->setLanguage($this->language); $this->em->persist($config); $this->em->flush(); } diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index f22472607..c38787ded 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -34,7 +34,8 @@ services: wallabag_core.doctrine.prefixed_naming_strategy: class: Wallabag\CoreBundle\Doctrine\Mapping\PrefixedNamingStrategy - arguments: [%database_table_prefix%] + arguments: + - %database_table_prefix% wallabag_core.graby: class: Graby\Graby @@ -48,6 +49,11 @@ services: wallabag_core.registration_confirmed: class: Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener - arguments: [@service_container, @doctrine.orm.entity_manager] + arguments: + - @doctrine.orm.entity_manager + - %theme% + - %items_on_page% + - %rss_limit% + - %language% tags: - { name: kernel.event_subscriber } diff --git a/src/Wallabag/CoreBundle/Tests/EventListener/RegistrationConfirmedListenerTest.php b/src/Wallabag/CoreBundle/Tests/EventListener/RegistrationConfirmedListenerTest.php new file mode 100644 index 000000000..137c097ca --- /dev/null +++ b/src/Wallabag/CoreBundle/Tests/EventListener/RegistrationConfirmedListenerTest.php @@ -0,0 +1,92 @@ +em = $this->getMockBuilder('Doctrine\ORM\EntityManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->listener = new RegistrationConfirmedListener( + $this->em, + 'baggy', + 20, + 50, + 'fr' + ); + + $this->dispatcher = new EventDispatcher(); + $this->dispatcher->addSubscriber($this->listener); + + $this->request = Request::create('/'); + $this->response = Response::create(); + } + + public function testWithInvalidUser() + { + $user = new User(); + $user->setEnabled(false); + + $event = new FilterUserResponseEvent( + $user, + $this->request, + $this->response + ); + + $this->em->expects($this->never())->method('persist'); + $this->em->expects($this->never())->method('flush'); + + $this->dispatcher->dispatch( + FOSUserEvents::REGISTRATION_CONFIRMED, + $event + ); + } + + public function testWithValidUser() + { + $user = new User(); + $user->setEnabled(true); + + $event = new FilterUserResponseEvent( + $user, + $this->request, + $this->response + ); + + $config = new Config($user); + $config->setTheme('baggy'); + $config->setItemsPerPage(20); + $config->setRssLimit(50); + $config->setLanguage('fr'); + + $this->em->expects($this->once()) + ->method('persist') + ->will($this->returnValue($config)); + $this->em->expects($this->once()) + ->method('flush'); + + $this->dispatcher->dispatch( + FOSUserEvents::REGISTRATION_CONFIRMED, + $event + ); + } +} From 1210dae10589515d6f3824c75639342c5e1d52dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 2 Oct 2015 14:51:41 +0200 Subject: [PATCH 07/13] remove old implementation for login/register/recover --- app/AppKernel.php | 1 + app/config/config.yml | 2 +- app/config/routing.yml | 23 +- app/config/security.yml | 4 +- config/deploy.rb | 4 +- config/deploy/staging.rb | 2 +- src/Wallabag/ApiBundle/Entity/AccessToken.php | 2 +- src/Wallabag/ApiBundle/Entity/AuthCode.php | 2 +- .../ApiBundle/Entity/RefreshToken.php | 2 +- .../CoreBundle/Command/InstallCommand.php | 2 +- .../Controller/ConfigController.php | 2 +- .../CoreBundle/Controller/RssController.php | 8 +- .../Controller/SecurityController.php | 153 --------- .../DataFixtures/ORM/LoadUserData.php | 4 +- src/Wallabag/CoreBundle/Entity/Config.php | 10 +- src/Wallabag/CoreBundle/Entity/Entry.php | 5 +- src/Wallabag/CoreBundle/Entity/Tag.php | 2 +- .../CoreBundle/Filter/EntryFilterType.php | 2 +- .../Form/Type/ForgotPasswordType.php | 2 +- .../CoreBundle/Form/Type/NewUserType.php | 2 +- .../Form/Type/UserInformationType.php | 2 +- .../CoreBundle/Helper/DetectActiveTheme.php | 2 +- .../UsernameRssTokenConverter.php | 4 +- .../views/themes/baggy/layout.html.twig | 2 +- .../themes/material/Security/login.html.twig | 2 +- .../views/themes/material/layout.html.twig | 3 +- .../Encoder/WallabagPasswordEncoder.php | 87 ----- .../WallabagAuthenticationProvider.php | 89 ----- .../WallabagUserPasswordValidator.php | 51 --- .../Tests/Controller/ConfigControllerTest.php | 4 +- .../Tests/Controller/RssControllerTest.php | 6 +- .../Controller/SecurityControllerTest.php | 319 ------------------ .../Tests/Helper/ContentProxyTest.php | 2 +- .../UsernameRssTokenConverterTest.php | 26 +- .../CoreBundle/Tests/WallabagCoreTestCase.php | 2 +- .../Entity/User.php | 19 +- .../Repository/UserRepository.php | 2 +- .../UserBundle/Resources/config/services.yml | 0 .../Resources/views/Default/index.html.twig | 1 + .../UserBundle/WallabagUserBundle.php | 9 + 40 files changed, 93 insertions(+), 773 deletions(-) delete mode 100644 src/Wallabag/CoreBundle/Controller/SecurityController.php delete mode 100644 src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php delete mode 100644 src/Wallabag/CoreBundle/Security/Authentication/Provider/WallabagAuthenticationProvider.php delete mode 100644 src/Wallabag/CoreBundle/Security/Validator/WallabagUserPasswordValidator.php delete mode 100644 src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php rename src/Wallabag/{CoreBundle => UserBundle}/Entity/User.php (83%) rename src/Wallabag/{CoreBundle => UserBundle}/Repository/UserRepository.php (94%) create mode 100644 src/Wallabag/UserBundle/Resources/config/services.yml create mode 100644 src/Wallabag/UserBundle/Resources/views/Default/index.html.twig create mode 100644 src/Wallabag/UserBundle/WallabagUserBundle.php diff --git a/app/AppKernel.php b/app/AppKernel.php index 6f8c3a6d6..6315fcde9 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -27,6 +27,7 @@ class AppKernel extends Kernel new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(), new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(), new FOS\OAuthServerBundle\FOSOAuthServerBundle(), + new Wallabag\UserBundle\WallabagUserBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { diff --git a/app/config/config.yml b/app/config/config.yml index 3c63ded3e..a4d18c6d8 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -158,7 +158,7 @@ liip_theme: fos_user: db_driver: orm firewall_name: main - user_class: Wallabag\CoreBundle\Entity\User + user_class: Wallabag\UserBundle\Entity\User registration: form: type: wallabag_user_registration diff --git a/app/config/routing.yml b/app/config/routing.yml index dabb48fa7..5fa28fba8 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -1,3 +1,8 @@ +wallabag_user: + resource: "@WallabagUserBundle/Controller/" + type: annotation + prefix: / + wallabag_api: resource: "@WallabagApiBundle/Resources/config/routing.yml" prefix: / @@ -10,15 +15,15 @@ doc-api: resource: "@NelmioApiDocBundle/Resources/config/routing.yml" prefix: /api/doc -login: - pattern: /login - defaults: { _controller: WallabagCoreBundle:Security:login } - -login_check: - pattern: /login_check - -logout: - path: /logout +#login: +# pattern: /login +# defaults: { _controller: WallabagCoreBundle:Security:login } +# +#login_check: +# pattern: /login_check +# +#logout: +# path: /logout rest : type : rest diff --git a/app/config/security.yml b/app/config/security.yml index 79a07c48e..d7d8c12b1 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -8,7 +8,7 @@ security: providers: administrators: - entity: { class: WallabagCoreBundle:User, property: username } + entity: { class: WallabagUserBundle:User, property: username } fos_userbundle: id: fos_user.user_provider.username @@ -49,6 +49,6 @@ security: - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/forgot-password, roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: /(unread|starred|archive).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/, roles: ROLE_USER } diff --git a/config/deploy.rb b/config/deploy.rb index be18ce5af..c2562965b 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -4,8 +4,8 @@ lock '3.4.0' set :application, 'wallabag' set :repo_url, 'git@github.com:wallabag/wallabag.git' -set :ssh_user, 'ssh_user' -server 'server_ip', user: fetch(:ssh_user), roles: %w{web app db} +set :ssh_user, 'framasoft_bag' +server '78.46.248.87', user: fetch(:ssh_user), roles: %w{web app db} set :scm, :git diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb index d67d7247d..ccd05b4d9 100644 --- a/config/deploy/staging.rb +++ b/config/deploy/staging.rb @@ -1,2 +1,2 @@ set :branch, 'v2' -set :deploy_to, '/var/www/' +set :deploy_to, '/var/www/v2.wallabag.org/web/' diff --git a/src/Wallabag/ApiBundle/Entity/AccessToken.php b/src/Wallabag/ApiBundle/Entity/AccessToken.php index d6cf0af5d..b1f4e7de2 100644 --- a/src/Wallabag/ApiBundle/Entity/AccessToken.php +++ b/src/Wallabag/ApiBundle/Entity/AccessToken.php @@ -25,7 +25,7 @@ class AccessToken extends BaseAccessToken protected $client; /** - * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\User") + * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") */ protected $user; } diff --git a/src/Wallabag/ApiBundle/Entity/AuthCode.php b/src/Wallabag/ApiBundle/Entity/AuthCode.php index 7873d97d9..81398158b 100644 --- a/src/Wallabag/ApiBundle/Entity/AuthCode.php +++ b/src/Wallabag/ApiBundle/Entity/AuthCode.php @@ -25,7 +25,7 @@ class AuthCode extends BaseAuthCode protected $client; /** - * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\User") + * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") */ protected $user; } diff --git a/src/Wallabag/ApiBundle/Entity/RefreshToken.php b/src/Wallabag/ApiBundle/Entity/RefreshToken.php index 74c564b77..be2c1d2e9 100644 --- a/src/Wallabag/ApiBundle/Entity/RefreshToken.php +++ b/src/Wallabag/ApiBundle/Entity/RefreshToken.php @@ -25,7 +25,7 @@ class RefreshToken extends BaseRefreshToken protected $client; /** - * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\User") + * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") */ protected $user; } diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index 1bd76ae36..140fdf9e3 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\NullOutput; -use Wallabag\CoreBundle\Entity\User; +use Wallabag\UserBundle\Entity\User; use Wallabag\CoreBundle\Entity\Config; class InstallCommand extends ContainerAwareCommand diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 27c323b71..ecfecc66d 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php @@ -7,7 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Wallabag\CoreBundle\Entity\Config; -use Wallabag\CoreBundle\Entity\User; +use Wallabag\UserBundle\Entity\User; use Wallabag\CoreBundle\Form\Type\ChangePasswordType; use Wallabag\CoreBundle\Form\Type\UserInformationType; use Wallabag\CoreBundle\Form\Type\NewUserType; diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php index 6121f3614..023a6228e 100644 --- a/src/Wallabag/CoreBundle/Controller/RssController.php +++ b/src/Wallabag/CoreBundle/Controller/RssController.php @@ -5,7 +5,7 @@ namespace Wallabag\CoreBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Bundle\FrameworkBundle\Controller\Controller; -use Wallabag\CoreBundle\Entity\User; +use Wallabag\UserBundle\Entity\User; use Wallabag\CoreBundle\Entity\Entry; use Pagerfanta\Adapter\DoctrineORMAdapter; use Pagerfanta\Pagerfanta; @@ -16,7 +16,7 @@ class RssController extends Controller * Shows unread entries for current user. * * @Route("/{username}/{token}/unread.xml", name="unread_rss", defaults={"_format"="xml"}) - * @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter") + * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") * * @return \Symfony\Component\HttpFoundation\Response */ @@ -29,7 +29,7 @@ class RssController extends Controller * Shows read entries for current user. * * @Route("/{username}/{token}/archive.xml", name="archive_rss") - * @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter") + * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") * * @return \Symfony\Component\HttpFoundation\Response */ @@ -42,7 +42,7 @@ class RssController extends Controller * Shows starred entries for current user. * * @Route("/{username}/{token}/starred.xml", name="starred_rss") - * @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter") + * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") * * @return \Symfony\Component\HttpFoundation\Response */ diff --git a/src/Wallabag/CoreBundle/Controller/SecurityController.php b/src/Wallabag/CoreBundle/Controller/SecurityController.php deleted file mode 100644 index f0a7ab6d8..000000000 --- a/src/Wallabag/CoreBundle/Controller/SecurityController.php +++ /dev/null @@ -1,153 +0,0 @@ -getSession(); - // get the login error if there is one - if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { - $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); - } else { - $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); - $session->remove(SecurityContext::AUTHENTICATION_ERROR); - } - - return $this->render('WallabagCoreBundle:Security:login.html.twig', array( - // last username entered by the user - 'last_username' => $session->get(SecurityContext::LAST_USERNAME), - 'error' => $error, - )); - } - - /** - * Request forgot password: show form. - * - * @Route("/forgot-password", name="forgot_password") - * - * @Method({"GET", "POST"}) - */ - public function forgotPasswordAction(Request $request) - { - $form = $this->createForm('forgot_password'); - $form->handleRequest($request); - - if ($form->isValid()) { - $user = $this->getDoctrine()->getRepository('WallabagCoreBundle:User')->findOneByEmail($form->get('email')->getData()); - - // generate "hard" token - $user->setConfirmationToken(rtrim(strtr(base64_encode(hash('sha256', uniqid(mt_rand(), true), true)), '+/', '-_'), '=')); - $user->setPasswordRequestedAt(new \DateTime()); - - $em = $this->getDoctrine()->getManager(); - $em->persist($user); - $em->flush(); - - $message = \Swift_Message::newInstance() - ->setSubject('Reset Password') - ->setFrom($this->container->getParameter('from_email')) - ->setTo($user->getEmail()) - ->setBody($this->renderView('WallabagCoreBundle:Mail:forgotPassword.txt.twig', array( - 'username' => $user->getUsername(), - 'confirmationUrl' => $this->generateUrl('forgot_password_reset', array('token' => $user->getConfirmationToken()), true), - ))) - ; - $this->get('mailer')->send($message); - - return $this->redirect($this->generateUrl('forgot_password_check_email', - array('email' => $this->getObfuscatedEmail($user->getEmail())) - )); - } - - return $this->render('WallabagCoreBundle:Security:forgotPassword.html.twig', array( - 'form' => $form->createView(), - )); - } - - /** - * Tell the user to check his email provider. - * - * @Route("/forgot-password/check-email", name="forgot_password_check_email") - * - * @Method({"GET"}) - */ - public function checkEmailAction(Request $request) - { - $email = $request->query->get('email'); - - if (empty($email)) { - // the user does not come from the forgotPassword action - return $this->redirect($this->generateUrl('forgot_password')); - } - - return $this->render('WallabagCoreBundle:Security:checkEmail.html.twig', array( - 'email' => $email, - )); - } - - /** - * Reset user password. - * - * @Route("/forgot-password/{token}", name="forgot_password_reset") - * - * @Method({"GET", "POST"}) - */ - public function resetAction(Request $request, $token) - { - $user = $this->getDoctrine()->getRepository('WallabagCoreBundle:User')->findOneByConfirmationToken($token); - - if (null === $user) { - throw $this->createNotFoundException(sprintf('No user found with token "%s"', $token)); - } - - $form = $this->createForm(new ResetPasswordType()); - $form->handleRequest($request); - - if ($form->isValid()) { - $user->setPassword($form->get('new_password')->getData()); - - $em = $this->getDoctrine()->getManager(); - $em->persist($user); - $em->flush(); - - $this->get('session')->getFlashBag()->add( - 'notice', - 'The password has been reset successfully' - ); - - return $this->redirect($this->generateUrl('login')); - } - - return $this->render('WallabagCoreBundle:Security:reset.html.twig', array( - 'token' => $token, - 'form' => $form->createView(), - )); - } - - /** - * Get the truncated email displayed when requesting the resetting. - * - * Keeping only the part following @ in the address. - * - * @param string $email - * - * @return string - */ - protected function getObfuscatedEmail($email) - { - if (false !== $pos = strpos($email, '@')) { - $email = '...'.substr($email, $pos); - } - - return $email; - } -} diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php index 811451da7..d48855da7 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php @@ -1,11 +1,11 @@ user = $user; } @@ -169,11 +169,11 @@ class Config /** * Set user. * - * @param \Wallabag\CoreBundle\Entity\User $user + * @param User $user * * @return Config */ - public function setUser(\Wallabag\CoreBundle\Entity\User $user = null) + public function setUser(User $user = null) { $this->user = $user; @@ -183,7 +183,7 @@ class Config /** * Get user. * - * @return \Wallabag\CoreBundle\Entity\User + * @return User */ public function getUser() { diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 9e81ba125..f6206a09f 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -7,6 +7,7 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; use Hateoas\Configuration\Annotation as Hateoas; use JMS\Serializer\Annotation\XmlRoot; +use Wallabag\UserBundle\Entity\User; /** * Entry. @@ -129,7 +130,7 @@ class Entry private $isPublic; /** - * @ORM\ManyToOne(targetEntity="User", inversedBy="entries") + * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="entries") */ private $user; @@ -142,7 +143,7 @@ class Entry /* * @param User $user */ - public function __construct(User $user) + public function __construct(Wallabag\UserBundle\Entity\User $user) { $this->user = $user; $this->tags = new ArrayCollection(); diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 97c4579f7..6067360f9 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -42,7 +42,7 @@ class Tag private $entries; /** - * @ORM\ManyToOne(targetEntity="User", inversedBy="tags") + * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="tags") */ private $user; diff --git a/src/Wallabag/CoreBundle/Filter/EntryFilterType.php b/src/Wallabag/CoreBundle/Filter/EntryFilterType.php index 2e6d6ff76..32de21ca8 100644 --- a/src/Wallabag/CoreBundle/Filter/EntryFilterType.php +++ b/src/Wallabag/CoreBundle/Filter/EntryFilterType.php @@ -7,7 +7,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Lexik\Bundle\FormFilterBundle\Filter\Query\QueryInterface; use Doctrine\ORM\EntityRepository; -use Wallabag\CoreBundle\Entity\User; +use Wallabag\UserBundle\Entity\User; class EntryFilterType extends AbstractType { diff --git a/src/Wallabag/CoreBundle/Form/Type/ForgotPasswordType.php b/src/Wallabag/CoreBundle/Form/Type/ForgotPasswordType.php index 9e95eb47a..5614d8b25 100644 --- a/src/Wallabag/CoreBundle/Form/Type/ForgotPasswordType.php +++ b/src/Wallabag/CoreBundle/Form/Type/ForgotPasswordType.php @@ -39,7 +39,7 @@ class ForgotPasswordType extends AbstractType public function validateEmail($email, ExecutionContextInterface $context) { $user = $this->doctrine - ->getRepository('WallabagCoreBundle:User') + ->getRepository('WallabagUserBundle:User') ->findOneByEmail($email); if (!$user) { diff --git a/src/Wallabag/CoreBundle/Form/Type/NewUserType.php b/src/Wallabag/CoreBundle/Form/Type/NewUserType.php index ea7bb7aef..8aabc8bbb 100644 --- a/src/Wallabag/CoreBundle/Form/Type/NewUserType.php +++ b/src/Wallabag/CoreBundle/Form/Type/NewUserType.php @@ -31,7 +31,7 @@ class NewUserType extends AbstractType public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'data_class' => 'Wallabag\CoreBundle\Entity\User', + 'data_class' => 'Wallabag\UserBundle\Entity\User', )); } diff --git a/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php b/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php index e3196d9cc..84f020131 100644 --- a/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php +++ b/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php @@ -27,7 +27,7 @@ class UserInformationType extends AbstractType public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'data_class' => 'Wallabag\CoreBundle\Entity\User', + 'data_class' => 'Wallabag\UserBundle\Entity\User', )); } diff --git a/src/Wallabag/CoreBundle/Helper/DetectActiveTheme.php b/src/Wallabag/CoreBundle/Helper/DetectActiveTheme.php index 446629db2..679186c08 100644 --- a/src/Wallabag/CoreBundle/Helper/DetectActiveTheme.php +++ b/src/Wallabag/CoreBundle/Helper/DetectActiveTheme.php @@ -4,7 +4,7 @@ namespace Wallabag\CoreBundle\Helper; use Liip\ThemeBundle\Helper\DeviceDetectionInterface; use Symfony\Component\Security\Core\SecurityContextInterface; -use Wallabag\CoreBundle\Entity\User; +use Wallabag\UserBundle\Entity\User; /** * This class intend to detect the active theme for the logged in user. diff --git a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php b/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php index 2771cf116..f7faa2c13 100644 --- a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php +++ b/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php @@ -7,7 +7,7 @@ use Doctrine\Common\Persistence\ManagerRegistry; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Wallabag\CoreBundle\Entity\User; +use Wallabag\UserBundle\Entity\User; /** * ParamConverter used in the RSS controller to retrieve the right user according to @@ -49,7 +49,7 @@ class UsernameRssTokenConverter implements ParamConverterInterface $em = $this->registry->getManagerForClass($configuration->getClass()); // Check, if class name is what we need - if ('Wallabag\CoreBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) { + if ('Wallabag\UserBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) { return false; } diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig index 3d573eaa7..de4ed2e78 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig @@ -52,7 +52,7 @@
  • {% trans %}config{% endtrans %}
  • {% trans %}about{% endtrans %}
  • -
  • {% trans %}logout{% endtrans %}
  • +
  • {% trans %}logout{% endtrans %}
  • {% endblock %} diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig index 10f380fe3..b0da42ce5 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Security/login.html.twig @@ -54,7 +54,7 @@ diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig index 10dede8ae..36e276f96 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig @@ -46,8 +46,7 @@
  • {% trans %}tags{% endtrans %}
  • {% trans %}config{% endtrans %}
  • {% trans %}howto{% endtrans %}
  • -
  • {% trans %}About{% endtrans %}
  • -
  • {% trans %}logout{% endtrans %}
  • +
  • {% trans %}logout{% endtrans %}
  • - {% endblock %} {% block footer %} From 8263e71192989dc0fd28a41ac22f9c5b32eb11c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 6 Oct 2015 07:44:10 +0200 Subject: [PATCH 13/13] use form widget for registration --- .../Registration/register_content.html.twig | 17 ++++++++--------- .../Registration/register_content.html.twig | 17 ++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/Wallabag/UserBundle/Resources/views/themes/baggy/Registration/register_content.html.twig b/src/Wallabag/UserBundle/Resources/views/themes/baggy/Registration/register_content.html.twig index f1f899d25..41f940065 100644 --- a/src/Wallabag/UserBundle/Resources/views/themes/baggy/Registration/register_content.html.twig +++ b/src/Wallabag/UserBundle/Resources/views/themes/baggy/Registration/register_content.html.twig @@ -1,6 +1,5 @@ {% trans_default_domain 'FOSUserBundle' %} -{{ form_errors(form) }} {{ form_widget(form._token) }} {% for flashMessage in app.session.flashbag.get('notice') %} @@ -9,26 +8,26 @@
    {{ form_errors(form.email) }} - - + {{ form_label(form.email) }} + {{ form_widget(form.email) }}
    {{ form_errors(form.username) }} - - + {{ form_label(form.username) }} + {{ form_widget(form.username) }}
    {{ form_errors(form.plainPassword.first) }} - - + {{ form_label(form.plainPassword.first) }} + {{ form_widget(form.plainPassword.first) }}
    {{ form_errors(form.plainPassword.second) }} - - + {{ form_label(form.plainPassword.second) }} + {{ form_widget(form.plainPassword.second) }}
    diff --git a/src/Wallabag/UserBundle/Resources/views/themes/material/Registration/register_content.html.twig b/src/Wallabag/UserBundle/Resources/views/themes/material/Registration/register_content.html.twig index b356f58c6..865a24aef 100644 --- a/src/Wallabag/UserBundle/Resources/views/themes/material/Registration/register_content.html.twig +++ b/src/Wallabag/UserBundle/Resources/views/themes/material/Registration/register_content.html.twig @@ -4,7 +4,6 @@
    - {{ form_errors(form) }} {{ form_widget(form._token) }} {% for flashMessage in app.session.flashbag.get('notice') %} @@ -13,26 +12,26 @@
    {{ form_errors(form.email) }} - - + {{ form_label(form.email) }} + {{ form_widget(form.email) }}
    {{ form_errors(form.username) }} - - + {{ form_label(form.username) }} + {{ form_widget(form.username) }}
    {{ form_errors(form.plainPassword.first) }} - - + {{ form_label(form.plainPassword.first) }} + {{ form_widget(form.plainPassword.first) }}
    {{ form_errors(form.plainPassword.second) }} - - + {{ form_label(form.plainPassword.second) }} + {{ form_widget(form.plainPassword.second) }}