├── .gitignore ├── Command ├── ActivateUserCommand.php ├── ChangePasswordCommand.php ├── CreateUserCommand.php ├── DeactivateUserCommand.php ├── DemoteSuperAdminCommand.php ├── InstallAcesCommand.php └── PromoteSuperAdminCommand.php ├── Controller ├── GroupController.php ├── SecurityController.php └── UserController.php ├── DependencyInjection ├── Configuration.php └── FOSUserExtension.php ├── Document ├── DefaultGroup.php ├── Group.php ├── GroupManager.php ├── User.php └── UserManager.php ├── Entity ├── DefaultGroup.php ├── Group.php ├── GroupManager.php ├── User.php └── UserManager.php ├── FOSUserBundle.php ├── Form ├── ChangePassword.php ├── ChangePasswordForm.php ├── GroupForm.php ├── ResetPassword.php ├── ResetPasswordForm.php └── UserForm.php ├── Model ├── Group.php ├── GroupInterface.php ├── GroupManager.php ├── GroupManagerInterface.php ├── User.php ├── UserInterface.php ├── UserManager.php └── UserManagerInterface.php ├── README.markdown ├── Resources ├── config │ ├── controller.xml │ ├── doctrine │ │ └── metadata │ │ │ ├── mongodb │ │ │ ├── FOS.UserBundle.Document.DefaultGroup.dcm.xml │ │ │ ├── FOS.UserBundle.Document.Group.dcm.xml │ │ │ └── FOS.UserBundle.Document.User.dcm.xml │ │ │ └── orm │ │ │ ├── FOS.UserBundle.Entity.DefaultGroup.dcm.xml │ │ │ ├── FOS.UserBundle.Entity.Group.dcm.xml │ │ │ └── FOS.UserBundle.Entity.User.dcm.xml │ ├── form.xml │ ├── listener.xml │ ├── mongodb.xml │ ├── orm.xml │ ├── routing │ │ ├── group.xml │ │ ├── security.xml │ │ └── user.xml │ ├── security.xml │ ├── templating.xml │ ├── twig.xml │ ├── util.xml │ ├── validation.xml │ └── validator.xml ├── doc │ └── index.rst ├── meta │ └── LICENSE └── views │ ├── Group │ ├── edit.html.twig │ ├── edit_content.html.twig │ ├── list.html.twig │ ├── list_content.html.twig │ ├── new.html.twig │ ├── new_content.html.twig │ ├── show.html.twig │ └── show_content.html.twig │ ├── Security │ └── login.html.twig │ ├── User │ ├── changePassword.html.twig │ ├── changePassword_content.html.twig │ ├── checkConfirmationEmail.html.twig │ ├── checkResettingEmail.html.twig │ ├── confirmationEmail.txt.twig │ ├── confirmed.html.twig │ ├── edit.html.twig │ ├── edit_content.html.twig │ ├── list.html.twig │ ├── list_content.html.twig │ ├── new.html.twig │ ├── new_content.html.twig │ ├── passwordAlreadyRequested.html.twig │ ├── requestResetPassword.html.twig │ ├── requestResetPassword_content.html.twig │ ├── resetPassword.html.twig │ ├── resetPassword_content.html.twig │ ├── resettingPasswordEmail.txt.twig │ ├── show.html.twig │ └── show_content.html.twig │ └── layout.html.twig ├── Security ├── Encoder │ └── EncoderFactory.php └── InteractiveLoginListener.php ├── Templating └── Helper │ └── SecurityHelper.php ├── Test └── WebTestCase.php ├── Tests ├── Command │ ├── ActivateUserCommandTest.php │ ├── CreateUserCommandTest.php │ ├── DeactivateUserCommandTest.php │ ├── DemoteSuperUserCommandTest.php │ └── PromoteSuperUserCommandTest.php ├── DependencyInjection │ └── FOSUserExtensionTest.php ├── Document │ └── DocumentUserManagerTest.php ├── Model │ ├── UserManagerTest.php │ └── UserTest.php ├── Security │ └── Encoder │ │ └── EncoderFactoryTest.php ├── Validation │ └── UserValidationTest.php └── bootstrap.php ├── Twig └── UserExtension.php ├── Util ├── Canonicalizer.php ├── CanonicalizerInterface.php ├── Mailer.php └── MailerInterface.php ├── Validator ├── Password.php ├── PasswordValidator.php ├── Unique.php └── UniqueValidator.php └── phpunit.xml.dist /.gitignore: -------------------------------------------------------------------------------- 1 | phpunit.xml 2 | nbproject 3 | catalog.xml 4 | -------------------------------------------------------------------------------- /Command/ActivateUserCommand.php: -------------------------------------------------------------------------------- 1 | 18 | * (c) Thibault Duplessis 19 | * 20 | * This source file is subject to the MIT license that is bundled 21 | * with this source code in the file LICENSE. 22 | */ 23 | 24 | /** 25 | * ActivateUserCommand. 26 | * 27 | * @package Bundle 28 | * @subpackage FOS\UserBundle 29 | * @author Antoine Hérault 30 | */ 31 | class ActivateUserCommand extends BaseCommand 32 | { 33 | /** 34 | * @see Command 35 | */ 36 | protected function configure() 37 | { 38 | $this 39 | ->setName('fos:user:activate') 40 | ->setDescription('Activate a user') 41 | ->setDefinition(array( 42 | new InputArgument('username', InputArgument::REQUIRED, 'The username'), 43 | )) 44 | ->setHelp(<<doctrine:user:activate command activates a super (will be able to log in) 46 | 47 | php app/console fos:user:activate matthieu 48 | EOT 49 | ); 50 | } 51 | 52 | /** 53 | * @see Command 54 | */ 55 | protected function execute(InputInterface $input, OutputInterface $output) 56 | { 57 | $this->container->get('security.context')->setToken(new UsernamePasswordToken('command.line', null, array(User::ROLE_SUPERADMIN))); 58 | 59 | $userManager = $this->container->get('fos_user.user_manager'); 60 | $user = $userManager->findUserByUsername($input->getArgument('username')); 61 | 62 | if (!$user) { 63 | throw new \InvalidArgumentException(sprintf('The user "%s" does not exist', $input->getArgument('username'))); 64 | } 65 | $user->setEnabled(true); 66 | 67 | $userManager->updateUser($user); 68 | 69 | $output->writeln(sprintf('User "%s" has been activated.', $user->getUsername())); 70 | } 71 | 72 | /** 73 | * @see Command 74 | */ 75 | protected function interact(InputInterface $input, OutputInterface $output) 76 | { 77 | if (!$input->getArgument('username')) { 78 | $username = $this->getHelper('dialog')->askAndValidate( 79 | $output, 80 | 'Please choose a username:', 81 | function($username) 82 | { 83 | if (empty($username)) { 84 | throw new \Exception('Username can not be empty'); 85 | } 86 | return $username; 87 | } 88 | ); 89 | $input->setArgument('username', $username); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Command/ChangePasswordCommand.php: -------------------------------------------------------------------------------- 1 | setName('fos:user:changePassword') 24 | ->setDescription('Change the password of a user.') 25 | ->setDefinition(array( 26 | new InputArgument('username', InputArgument::REQUIRED, 'The username'), 27 | new InputArgument('password', InputArgument::REQUIRED, 'The password'), 28 | )) 29 | ->setHelp(<<fos:user:changePassword command changes the password of a user: 31 | 32 | php app/console fos:user:changePassword matthieu 33 | 34 | This interactive shell will first ask you for a password. 35 | 36 | You can alternatively specify the password as a second argument: 37 | 38 | php app/console fos:user:changePassword matthieu mypassword 39 | 40 | EOT 41 | ); 42 | } 43 | 44 | /** 45 | * @see Command 46 | */ 47 | protected function execute(InputInterface $input, OutputInterface $output) 48 | { 49 | $this->container->get('security.context')->setToken(new UsernamePasswordToken('command.line', null, array(User::ROLE_SUPERADMIN))); 50 | 51 | $userManager = $this->container->get('fos_user.user_manager'); 52 | $user = $userManager->findUserByUsername($input->getArgument('username')); 53 | if (!$user) { 54 | throw new \InvalidArgumentException(sprintf('User identified by "%s" username does not exist.', $input->getArgument('username'))); 55 | } 56 | $user->setPlainPassword($input->getArgument('password')); 57 | $userManager->updateUser($user); 58 | 59 | $output->writeln(sprintf('Changed password for user %s', $user->getUsername())); 60 | } 61 | 62 | /** 63 | * @see Command 64 | */ 65 | protected function interact(InputInterface $input, OutputInterface $output) 66 | { 67 | if (!$input->getArgument('username')) { 68 | $username = $this->getHelper('dialog')->askAndValidate( 69 | $output, 70 | 'Please give the username:', 71 | function($username) 72 | { 73 | if (empty($username)) { 74 | throw new \Exception('Username can not be empty'); 75 | } 76 | return $username; 77 | } 78 | ); 79 | $input->setArgument('username', $username); 80 | } 81 | 82 | if (!$input->getArgument('password')) { 83 | $password = $this->getHelper('dialog')->askAndValidate( 84 | $output, 85 | 'Please enter the new password:', 86 | function($password) 87 | { 88 | if (empty($password)) { 89 | throw new \Exception('Password can not be empty'); 90 | } 91 | return $password; 92 | } 93 | ); 94 | $input->setArgument('password', $password); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Command/CreateUserCommand.php: -------------------------------------------------------------------------------- 1 | 24 | * (c) Thibault Duplessis 25 | * 26 | * This source file is subject to the MIT license that is bundled 27 | * with this source code in the file LICENSE. 28 | */ 29 | 30 | /** 31 | * CreateUserCommand. 32 | * 33 | * @package Bundle 34 | * @subpackage FOS\UserBundle 35 | * @author Matthieu Bontemps 36 | * @author Thibault Duplessis 37 | */ 38 | class CreateUserCommand extends BaseCommand 39 | { 40 | /** 41 | * @see Command 42 | */ 43 | protected function configure() 44 | { 45 | $this 46 | ->setName('fos:user:create') 47 | ->setDescription('Create a user.') 48 | ->setDefinition(array( 49 | new InputArgument('username', InputArgument::REQUIRED, 'The username'), 50 | new InputArgument('email', InputArgument::REQUIRED, 'The email'), 51 | new InputArgument('password', InputArgument::REQUIRED, 'The password'), 52 | new InputOption('super-admin', null, InputOption::VALUE_NONE, 'Set the user as super admin'), 53 | new InputOption('inactive', null, InputOption::VALUE_NONE, 'Set the user as inactive'), 54 | )) 55 | ->setHelp(<<fos:user:create command creates a user: 57 | 58 | php app/console fos:user:create matthieu 59 | 60 | This interactive shell will first ask you for a password. 61 | 62 | You can alternatively specify the password as a second argument: 63 | 64 | php app/console fos:user:create matthieu mypassword 65 | 66 | You can create a super admin via the super-admin flag: 67 | 68 | php app/console fos:user:create admin --super-admin 69 | 70 | You can create an inactive user (will not be able to log in): 71 | 72 | php app/console fos:user:create thibault --inactive 73 | 74 | EOT 75 | ); 76 | } 77 | 78 | /** 79 | * @see Command 80 | */ 81 | protected function execute(InputInterface $input, OutputInterface $output) 82 | { 83 | $this->container->get('security.context')->setToken(new UsernamePasswordToken('command.line', null, array(User::ROLE_SUPERADMIN))); 84 | 85 | $userManager = $this->container->get('fos_user.user_manager'); 86 | $user = $userManager->createUser(); 87 | $user->setUsername($input->getArgument('username')); 88 | $user->setEmail($input->getArgument('email')); 89 | $user->setPlainPassword($input->getArgument('password')); 90 | $user->setEnabled(!$input->getOption('inactive')); 91 | $user->setSuperAdmin(!!$input->getOption('super-admin')); 92 | $userManager->updateUser($user); 93 | 94 | if ($this->container->has('security.acl.provider')) { 95 | $provider = $this->container->get('security.acl.provider'); 96 | $oid = ObjectIdentity::fromDomainObject($user); 97 | $acl = $provider->createAcl($oid); 98 | $acl->insertObjectAce(UserSecurityIdentity::fromAccount($user), MaskBuilder::MASK_OWNER); 99 | $provider->updateAcl($acl); 100 | } 101 | 102 | $output->writeln(sprintf('Created user %s', $user->getUsername())); 103 | } 104 | 105 | /** 106 | * @see Command 107 | */ 108 | protected function interact(InputInterface $input, OutputInterface $output) 109 | { 110 | if (!$input->getArgument('username')) { 111 | $username = $this->getHelper('dialog')->askAndValidate( 112 | $output, 113 | 'Please choose a username:', 114 | function($username) 115 | { 116 | if (empty($username)) { 117 | throw new \Exception('Username can not be empty'); 118 | } 119 | return $username; 120 | } 121 | ); 122 | $input->setArgument('username', $username); 123 | } 124 | 125 | if (!$input->getArgument('email')) { 126 | $email = $this->getHelper('dialog')->askAndValidate( 127 | $output, 128 | 'Please choose an email:', 129 | function($email) 130 | { 131 | if (empty($email)) { 132 | throw new \Exception('Email can not be empty'); 133 | } 134 | return $email; 135 | } 136 | ); 137 | $input->setArgument('email', $email); 138 | } 139 | 140 | if (!$input->getArgument('password')) { 141 | $password = $this->getHelper('dialog')->askAndValidate( 142 | $output, 143 | 'Please choose a password:', 144 | function($password) 145 | { 146 | if (empty($password)) { 147 | throw new \Exception('Password can not be empty'); 148 | } 149 | return $password; 150 | } 151 | ); 152 | $input->setArgument('password', $password); 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /Command/DeactivateUserCommand.php: -------------------------------------------------------------------------------- 1 | 18 | * (c) Thibault Duplessis 19 | * 20 | * This source file is subject to the MIT license that is bundled 21 | * with this source code in the file LICENSE. 22 | */ 23 | 24 | /** 25 | * DeactivateUserCommand. 26 | * 27 | * @package Bundle 28 | * @subpackage FOS\UserBundle 29 | * @author Antoine Hérault 30 | */ 31 | class DeactivateUserCommand extends BaseCommand 32 | { 33 | /** 34 | * @see Command 35 | */ 36 | protected function configure() 37 | { 38 | $this 39 | ->setName('fos:user:deactivate') 40 | ->setDescription('Deactivate a user') 41 | ->setDefinition(array( 42 | new InputArgument('username', InputArgument::REQUIRED, 'The username'), 43 | )) 44 | ->setHelp(<<fos:user:deactivate command deactivates a user (will not be able to log in) 46 | 47 | php app/console fos:user:deactivate matthieu 48 | EOT 49 | ); 50 | } 51 | 52 | /** 53 | * @see Command 54 | */ 55 | protected function execute(InputInterface $input, OutputInterface $output) 56 | { 57 | $this->container->get('security.context')->setToken(new UsernamePasswordToken('command.line', null, array(User::ROLE_SUPERADMIN))); 58 | 59 | $userManager = $this->container->get('fos_user.user_manager'); 60 | $user = $userManager->findUserByUsername($input->getArgument('username')); 61 | 62 | if (!$user) { 63 | throw new \InvalidArgumentException(sprintf('The user "%s" does not exist', $input->getArgument('username'))); 64 | } 65 | $user->setEnabled(false); 66 | 67 | $userManager->updateUser($user); 68 | 69 | $output->writeln(sprintf('User "%s" has been deactivated.', $user->getUsername())); 70 | } 71 | 72 | /** 73 | * @see Command 74 | */ 75 | protected function interact(InputInterface $input, OutputInterface $output) 76 | { 77 | if (!$input->getArgument('username')) { 78 | $username = $this->getHelper('dialog')->askAndValidate( 79 | $output, 80 | 'Please choose a username:', 81 | function($username) 82 | { 83 | if (empty($username)) { 84 | throw new \Exception('Username can not be empty'); 85 | } 86 | return $username; 87 | } 88 | ); 89 | $input->setArgument('username', $username); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Command/DemoteSuperAdminCommand.php: -------------------------------------------------------------------------------- 1 | 18 | * (c) Thibault Duplessis 19 | * 20 | * This source file is subject to the MIT license that is bundled 21 | * with this source code in the file LICENSE. 22 | */ 23 | 24 | /** 25 | * DemoteSuperAdminCommand. 26 | * 27 | * @package Bundle 28 | * @subpackage FOS\UserBundle 29 | * @author Antoine Hérault 30 | */ 31 | class DemoteSuperAdminCommand extends BaseCommand 32 | { 33 | /** 34 | * @see Command 35 | */ 36 | protected function configure() 37 | { 38 | $this 39 | ->setName('fos:user:demote') 40 | ->setDescription('Demote a super administrator as a simple user') 41 | ->setDefinition(array( 42 | new InputArgument('username', InputArgument::REQUIRED, 'The username'), 43 | )) 44 | ->setHelp(<<fos:user:demote command demotes a super administrator as a simple user 46 | 47 | php app/console fos:user:demote matthieu 48 | EOT 49 | ); 50 | } 51 | 52 | /** 53 | * @see Command 54 | */ 55 | protected function execute(InputInterface $input, OutputInterface $output) 56 | { 57 | $this->container->get('security.context')->setToken(new UsernamePasswordToken('command.line', null, array(User::ROLE_SUPERADMIN))); 58 | 59 | $userManager = $this->container->get('fos_user.user_manager'); 60 | $user = $userManager->findUserByUsername($input->getArgument('username')); 61 | 62 | if (!$user) { 63 | throw new \InvalidArgumentException(sprintf('The user "%s" does not exist', $input->getArgument('username'))); 64 | } 65 | $user->setSuperAdmin(false); 66 | 67 | $userManager->updateUser($user); 68 | 69 | $output->writeln(sprintf('Super administrator "%s" has been demoted as a simple user.', $user->getUsername())); 70 | } 71 | 72 | /** 73 | * @see Command 74 | */ 75 | protected function interact(InputInterface $input, OutputInterface $output) 76 | { 77 | if (!$input->getArgument('username')) { 78 | $username = $this->getHelper('dialog')->askAndValidate( 79 | $output, 80 | 'Please choose a username:', 81 | function($username) 82 | { 83 | if (empty($username)) { 84 | throw new \Exception('Username can not be empty'); 85 | } 86 | return $username; 87 | } 88 | ); 89 | $input->setArgument('username', $username); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Command/InstallAcesCommand.php: -------------------------------------------------------------------------------- 1 | 21 | * 22 | * This source file is subject to the MIT license that is bundled 23 | * with this source code in the file LICENSE. 24 | */ 25 | 26 | /** 27 | * This command installs global access control entries (ACEs) 28 | * 29 | * @author Johannes M. Schmitt 30 | */ 31 | class InstallAcesCommand extends BaseCommand 32 | { 33 | /** 34 | * @see Command 35 | */ 36 | protected function configure() 37 | { 38 | $this 39 | ->setName('fos:user:installAces') 40 | ->setDescription('Installs global ACEs') 41 | ->setHelp(<<container->has('security.acl.provider')) { 53 | $output->writeln('You must setup the ACL system, see the Symfony2 documentation for how to do this.'); 54 | return; 55 | } 56 | 57 | $provider = $this->container->get('security.acl.provider'); 58 | $oid = new ObjectIdentity('class', $this->container->get('fos_user.user_manager')->getClass()); 59 | try { 60 | $acl = $provider->createAcl($oid); 61 | } catch (AclAlreadyExistsException $exists) { 62 | $output->writeln('You already installed the global ACEs.'); 63 | return; 64 | } 65 | 66 | // insert ACEs for the super admin 67 | $sid = new RoleSecurityIdentity(User::ROLE_SUPERADMIN); 68 | $acl->insertClassAce($sid, MaskBuilder::MASK_IDDQD); 69 | 70 | $provider->updateAcl($acl); 71 | 72 | $output->writeln('Global ACEs have been installed.'); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Command/PromoteSuperAdminCommand.php: -------------------------------------------------------------------------------- 1 | 18 | * (c) Thibault Duplessis 19 | * 20 | * This source file is subject to the MIT license that is bundled 21 | * with this source code in the file LICENSE. 22 | */ 23 | 24 | /** 25 | * CreateUserCommand. 26 | * 27 | * @package Bundle 28 | * @subpackage FOS\UserBundle 29 | * @author Matthieu Bontemps 30 | * @author Thibault Duplessis 31 | */ 32 | class PromoteSuperAdminCommand extends BaseCommand 33 | { 34 | /** 35 | * @see Command 36 | */ 37 | protected function configure() 38 | { 39 | $this 40 | ->setName('fos:user:promote') 41 | ->setDescription('Promotes a user as a super administrator') 42 | ->setDefinition(array( 43 | new InputArgument('username', InputArgument::REQUIRED, 'The username'), 44 | )) 45 | ->setHelp(<<fos:user:promote command promotes a user as a super administrator 47 | 48 | php app/console fos:user:promote matthieu 49 | EOT 50 | ); 51 | } 52 | 53 | /** 54 | * @see Command 55 | */ 56 | protected function execute(InputInterface $input, OutputInterface $output) 57 | { 58 | $this->container->get('security.context')->setToken(new UsernamePasswordToken('command.line', null, array(User::ROLE_SUPERADMIN))); 59 | 60 | $userManager = $this->container->get('fos_user.user_manager'); 61 | $user = $userManager->findUserByUsername($input->getArgument('username')); 62 | 63 | if (!$user) { 64 | throw new \InvalidArgumentException(sprintf('The user "%s" does not exist', $input->getArgument('username'))); 65 | } 66 | $user->setSuperAdmin(true); 67 | 68 | $userManager->updateUser($user); 69 | 70 | $output->writeln(sprintf('User "%s" has been promoted as a super administrator.', $user->getUsername())); 71 | } 72 | 73 | /** 74 | * @see Command 75 | */ 76 | protected function interact(InputInterface $input, OutputInterface $output) 77 | { 78 | if (!$input->getArgument('username')) { 79 | $username = $this->getHelper('dialog')->askAndValidate( 80 | $output, 81 | 'Please choose a username:', 82 | function($username) 83 | { 84 | if (empty($username)) { 85 | throw new \Exception('Username can not be empty'); 86 | } 87 | return $username; 88 | } 89 | ); 90 | $input->setArgument('username', $username); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Controller/GroupController.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Christophe Coevoet 6 | * 7 | * This source file is subject to the MIT license that is bundled 8 | * with this source code in the file LICENSE. 9 | */ 10 | 11 | namespace FOS\UserBundle\Controller; 12 | 13 | use Symfony\Component\DependencyInjection\ContainerAware; 14 | use Symfony\Component\HttpFoundation\RedirectResponse; 15 | 16 | use FOS\UserBundle\Model\Group; 17 | 18 | /** 19 | * RESTful controller managing group CRUD 20 | */ 21 | class GroupController extends ContainerAware 22 | { 23 | /** 24 | * Show all groups 25 | */ 26 | public function listAction() 27 | { 28 | $groups = $this->container->get('fos_user.group_manager')->findGroups(); 29 | 30 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Group:list.html.'.$this->getEngine(), array('groups' => $groups)); 31 | } 32 | 33 | /** 34 | * Show one group 35 | */ 36 | public function showAction($groupname) 37 | { 38 | $group = $this->findGroupBy('name', $groupname); 39 | 40 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Group:show.html.'.$this->getEngine(), array('group' => $group)); 41 | } 42 | 43 | /** 44 | * Edit one group, show the edit form 45 | */ 46 | public function editAction($groupname) 47 | { 48 | $group = $this->findGroupBy('name', $groupname); 49 | $form = $this->container->get('fos_user.form.group'); 50 | 51 | $form->process($group); 52 | 53 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Group:edit.html.'.$this->getEngine(), array( 54 | 'form' => $form, 55 | 'groupname' => $group->getName() 56 | )); 57 | } 58 | 59 | /** 60 | * Update a group 61 | */ 62 | public function updateAction($groupname) 63 | { 64 | $group = $this->findGroupBy('name', $groupname); 65 | $form = $this->container->get('fos_user.form.group'); 66 | 67 | $process = $form->process($group); 68 | if ($process) { 69 | $this->setFlash('fos_user_group_update', 'success'); 70 | $groupUrl = $this->container->get('router')->generate('fos_user_group_show', array('groupname' => $group->getName())); 71 | return new RedirectResponse($groupUrl); 72 | } 73 | 74 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Group:edit.html.'.$this->getEngine(), array( 75 | 'form' => $form, 76 | 'groupname' => $group->getName() 77 | )); 78 | } 79 | 80 | /** 81 | * Show the new form 82 | */ 83 | public function newAction() 84 | { 85 | $form = $this->container->get('fos_user.form.group'); 86 | 87 | $form->process(); 88 | 89 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Group:new.html.'.$this->getEngine(), array( 90 | 'form' => $form 91 | )); 92 | } 93 | 94 | /** 95 | * Create a group 96 | */ 97 | public function createAction() 98 | { 99 | $form = $this->container->get('fos_user.form.group'); 100 | 101 | $process = $form->process(); 102 | if ($process) { 103 | $this->container->get('session')->setFlash('fos_user_group_update', 'success'); 104 | $parameters = array('groupname' => $form->getData('group')->getName()); 105 | $url = $this->container->get('router')->generate('fos_user_group_show', $parameters); 106 | return new RedirectResponse($url); 107 | } 108 | 109 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Group:new.html.'.$this->getEngine(), array( 110 | 'form' => $form 111 | )); 112 | } 113 | 114 | /** 115 | * Delete one group 116 | */ 117 | public function deleteAction($groupname) 118 | { 119 | $group = $this->findGroupBy('name', $groupname); 120 | $this->container->get('fos_user.group_manager')->deleteGroup($group); 121 | $this->setFlash('fos_user_group_delete', 'success'); 122 | 123 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_group_list')); 124 | } 125 | 126 | /** 127 | * Find a group by a specific property 128 | * 129 | * @param string $key property name 130 | * @param mixed $value property value 131 | * @throws NotFoundException if user does not exist 132 | * @return Group 133 | */ 134 | protected function findGroupBy($key, $value) 135 | { 136 | if (!empty($value)) { 137 | $group = $this->container->get('fos_user.group_manager')->{'findGroupBy'.ucfirst($key)}($value); 138 | } 139 | 140 | if (empty($group)) { 141 | throw new NotFoundHttpException(sprintf('The group with "%s" does not exist for value "%s"', $key, $value)); 142 | } 143 | 144 | return $group; 145 | } 146 | 147 | protected function getEngine() 148 | { 149 | return $this->container->getParameter('fos_user.template.engine'); 150 | } 151 | 152 | protected function setFlash($action, $value) 153 | { 154 | $this->container->get('session')->setFlash($action, $value); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Controller/SecurityController.php: -------------------------------------------------------------------------------- 1 | container->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { 15 | $error = $this->container->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR); 16 | } else { 17 | $error = $this->container->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR); 18 | $this->container->get('request')->getSession()->remove(SecurityContext::AUTHENTICATION_ERROR); 19 | } 20 | 21 | if ($error) { 22 | // TODO: this is a potential security risk (see http://trac.symfony-project.org/ticket/9523) 23 | $error = $error->getMessage(); 24 | } 25 | 26 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Security:login.html.'.$this->getEngine(), array( 27 | // last username entered by the user 28 | 'last_username' => $this->container->get('request')->getSession()->get(SecurityContext::LAST_USERNAME), 29 | 'error' => $error, 30 | )); 31 | } 32 | 33 | public function logoutAction() 34 | { 35 | throw new \RuntimeException('You must activate the logout in your security firewall configuration.'); 36 | } 37 | 38 | protected function getEngine() 39 | { 40 | return $this->container->getParameter('fos_user.template.engine'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Controller/UserController.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * This source file is subject to the MIT license that is bundled 7 | * with this source code in the file LICENSE. 8 | */ 9 | 10 | namespace FOS\UserBundle\Controller; 11 | 12 | use Symfony\Component\Security\Acl\Permission\MaskBuilder; 13 | use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; 14 | use Symfony\Component\Security\Acl\Domain\ObjectIdentity; 15 | use Symfony\Component\DependencyInjection\ContainerAware; 16 | use Symfony\Component\HttpFoundation\RedirectResponse; 17 | 18 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 19 | use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; 20 | use Symfony\Component\Security\Core\Exception\AccessDeniedException; 21 | 22 | use FOS\UserBundle\Model\UserInterface; 23 | 24 | /** 25 | * RESTful controller managing user CRUD 26 | */ 27 | class UserController extends ContainerAware 28 | { 29 | /** 30 | * Show all users 31 | */ 32 | public function listAction() 33 | { 34 | $users = $this->container->get('fos_user.user_manager')->findUsers(); 35 | 36 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:list.html.'.$this->getEngine(), array('users' => $users)); 37 | } 38 | 39 | /** 40 | * Show one user 41 | */ 42 | public function showAction($username) 43 | { 44 | $user = $this->findUserBy('username', $username); 45 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:show.html.'.$this->getEngine(), array('user' => $user)); 46 | } 47 | 48 | /** 49 | * Edit one user, show the edit form 50 | */ 51 | public function editAction($username) 52 | { 53 | $user = $this->findUserBy('username', $username); 54 | $form = $this->container->get('fos_user.form.user'); 55 | 56 | $form->process($user); 57 | 58 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:edit.html.'.$this->getEngine(), array( 59 | 'form' => $form, 60 | 'username' => $user->getUsername() 61 | )); 62 | } 63 | 64 | /** 65 | * Update a user 66 | */ 67 | public function updateAction($username) 68 | { 69 | $user = $this->findUserBy('username', $username); 70 | $form = $this->container->get('fos_user.form.user'); 71 | 72 | $process = $form->process($user); 73 | if ($process) { 74 | $this->setFlash('fos_user_user_update', 'success'); 75 | $userUrl = $this->container->get('router')->generate('fos_user_user_show', array('username' => $user->getUsername())); 76 | return new RedirectResponse($userUrl); 77 | } 78 | 79 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:edit.html.'.$this->getEngine(), array( 80 | 'form' => $form, 81 | 'username' => $user->getUsername() 82 | )); 83 | } 84 | 85 | /** 86 | * Show the new form 87 | */ 88 | public function newAction() 89 | { 90 | $form = $this->container->get('fos_user.form.user'); 91 | 92 | $form->process(); 93 | 94 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:new.html.'.$this->getEngine(), array( 95 | 'form' => $form 96 | )); 97 | } 98 | 99 | /** 100 | * Create a user and send a confirmation email 101 | */ 102 | public function createAction() 103 | { 104 | $form = $this->container->get('fos_user.form.user'); 105 | 106 | $process = $form->process(null, $this->container->getParameter('fos_user.email.confirmation.enabled')); 107 | if ($process) { 108 | 109 | $user = $form->getData(); 110 | 111 | if ($this->container->getParameter('fos_user.email.confirmation.enabled')) { 112 | $this->container->get('fos_user.util.mailer')->sendConfirmationEmailMessage($user, $this->getEngine()); 113 | $this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail()); 114 | $route = 'fos_user_user_check_confirmation_email'; 115 | } else { 116 | $this->authenticateUser($user); 117 | $route = 'fos_user_user_confirmed'; 118 | } 119 | 120 | if ($this->container->has('security.acl.provider')) { 121 | $provider = $this->container->get('security.acl.provider'); 122 | $acl = $provider->createAcl(ObjectIdentity::fromDomainObject($user)); 123 | $acl->insertObjectAce(UserSecurityIdentity::fromAccount($user), MaskBuilder::MASK_OWNER); 124 | $provider->updateAcl($acl); 125 | } 126 | 127 | $this->setFlash('fos_user_user_create', 'success'); 128 | $url = $this->container->get('router')->generate($route); 129 | return new RedirectResponse($url); 130 | } 131 | 132 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:new.html.'.$this->getEngine(), array( 133 | 'form' => $form 134 | )); 135 | } 136 | 137 | /** 138 | * Tell the user to check his email provider 139 | */ 140 | public function checkConfirmationEmailAction() 141 | { 142 | $email = $this->container->get('session')->get('fos_user_send_confirmation_email/email'); 143 | $this->container->get('session')->remove('fos_user_send_confirmation_email/email'); 144 | $user = $this->findUserBy('email', $email); 145 | 146 | $this->setFlash('fos_user_user_confirm', 'success'); 147 | 148 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:checkConfirmationEmail.html.'.$this->getEngine(), array( 149 | 'user' => $user, 150 | )); 151 | } 152 | 153 | /** 154 | * Receive the confirmation token from user email provider, login the user 155 | */ 156 | public function confirmAction($token) 157 | { 158 | $user = $this->findUserBy('confirmationToken', $token); 159 | $user->setConfirmationToken(null); 160 | $user->setEnabled(true); 161 | 162 | $this->container->get('fos_user.user_manager')->updateUser($user); 163 | $this->authenticateUser($user); 164 | 165 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_user_confirmed')); 166 | } 167 | 168 | /** 169 | * Tell the user his account is now confirmed 170 | */ 171 | public function confirmedAction() 172 | { 173 | $user = $this->getUser(); 174 | 175 | $this->setFlash('fos_user_user_confirmed', 'success'); 176 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:confirmed.html.'.$this->getEngine(), array( 177 | 'user' => $user, 178 | )); 179 | } 180 | 181 | /** 182 | * Delete one user 183 | */ 184 | public function deleteAction($username) 185 | { 186 | $user = $this->findUserBy('username', $username); 187 | $this->container->get('fos_user.user_manager')->deleteUser($user); 188 | $this->setFlash('fos_user_user_delete', 'success'); 189 | 190 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_user_list')); 191 | } 192 | 193 | /** 194 | * Change user password: show form 195 | */ 196 | public function changePasswordAction() 197 | { 198 | $user = $this->getUser(); 199 | $form = $this->container->get('fos_user.form.change_password'); 200 | $form->process($user); 201 | 202 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:changePassword.html.'.$this->getEngine(), array( 203 | 'form' => $form 204 | )); 205 | } 206 | 207 | /** 208 | * Change user password: submit form 209 | */ 210 | public function changePasswordUpdateAction() 211 | { 212 | $user = $this->getUser(); 213 | $form = $this->container->get('fos_user.form.change_password'); 214 | 215 | $process = $form->process($user); 216 | if ($process) { 217 | $this->setFlash('fos_user_user_password', 'success'); 218 | $url = $this->container->get('router')->generate('fos_user_user_show', array('username' => $user->getUsername())); 219 | return new RedirectResponse($url); 220 | } 221 | 222 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:changePassword.html.'.$this->getEngine(), array( 223 | 'form' => $form 224 | )); 225 | } 226 | 227 | /** 228 | * Request reset user password: show form 229 | */ 230 | public function requestResetPasswordAction() 231 | { 232 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:requestResetPassword.html.'.$this->getEngine()); 233 | } 234 | 235 | /** 236 | * Request reset user password: submit form and send email 237 | */ 238 | public function sendResettingEmailAction() 239 | { 240 | $user = $this->findUserBy('username', $this->container->get('request')->get('username')); 241 | 242 | if ($user->isPasswordRequestNonExpired($this->getPasswordRequestTtl())) { 243 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:passwordAlreadyRequested.html.'.$this->getEngine()); 244 | } 245 | 246 | $user->generateConfirmationToken(); 247 | $user->setPasswordRequestedAt(new \DateTime()); 248 | $this->container->get('fos_user.user_manager')->updateUser($user); 249 | $this->container->get('session')->set('fos_user_send_resetting_email/email', $user->getEmail()); 250 | $this->container->get('fos_user.util.mailer')->sendResettingEmailMessage($user, $this->getEngine()); 251 | 252 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_user_check_resetting_email')); 253 | } 254 | 255 | /** 256 | * Tell the user to check his email provider 257 | */ 258 | public function checkResettingEmailAction() 259 | { 260 | $email = $this->container->get('session')->get('fos_user_send_resetting_email/email'); 261 | $this->container->get('session')->remove('fos_user_send_resetting_email/email'); 262 | $user = $this->container->get('fos_user.user_manager')->findUserByEmail($email); 263 | if (empty($user)) { 264 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_user_request_reset_password')); 265 | } 266 | 267 | $this->setFlash('fos_user_user_reset', 'success'); 268 | 269 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:checkResettingEmail.html.'.$this->getEngine(), array( 270 | 'user' => $user, 271 | )); 272 | } 273 | 274 | /** 275 | * Reset user password: show form 276 | */ 277 | public function resetPasswordAction($token) 278 | { 279 | $user = $this->findUserBy('confirmationToken', $token); 280 | 281 | if (!$user->isPasswordRequestNonExpired($this->getPasswordRequestTtl())) { 282 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_user_request_reset_password')); 283 | } 284 | 285 | $form = $this->container->get('fos_user.form.reset_password'); 286 | $form->process($user); 287 | 288 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:resetPassword.html.'.$this->getEngine(), array( 289 | 'token' => $token, 290 | 'form' => $form 291 | )); 292 | } 293 | 294 | /** 295 | * Reset user password: submit form 296 | */ 297 | public function resetPasswordUpdateAction($token) 298 | { 299 | $user = $this->findUserBy('confirmationToken', $token); 300 | 301 | if (!$user->isPasswordRequestNonExpired($this->getPasswordRequestTtl())) { 302 | return new RedirectResponse( $this->container->get('router')->generate('fos_user_user_request_reset_password')); 303 | } 304 | 305 | $form = $this->container->get('fos_user.form.reset_password'); 306 | 307 | $process = $form->process($user); 308 | if ($process) { 309 | $this->authenticateUser($user); 310 | 311 | $this->setFlash('fos_user_user_resetted', 'success'); 312 | $url = $this->container->get('router')->generate('fos_user_user_show', array('username' => $user->getUsername())); 313 | return new RedirectResponse($url); 314 | } 315 | 316 | return $this->container->get('templating')->renderResponse('FOSUserBundle:User:resetPassword.html.'.$this->getEngine(), array( 317 | 'token' => $token, 318 | 'form' => $form 319 | )); 320 | } 321 | 322 | /** 323 | * Get a user from the security context 324 | * 325 | * @throws AccessDeniedException if no user is authenticated 326 | * @return User 327 | */ 328 | protected function getUser() 329 | { 330 | $user = $this->container->get('security.context')->getToken()->getUser(); 331 | if (!$user) { 332 | throw new AccessDeniedException('A logged in user is required.'); 333 | } 334 | 335 | return $user; 336 | } 337 | 338 | /** 339 | * Find a user by a specific property 340 | * 341 | * @param string $key property name 342 | * @param mixed $value property value 343 | * @throws NotFoundException if user does not exist 344 | * @return User 345 | */ 346 | protected function findUserBy($key, $value) 347 | { 348 | if (!empty($value)) { 349 | $user = $this->container->get('fos_user.user_manager')->{'findUserBy'.ucfirst($key)}($value); 350 | } 351 | 352 | if (empty($user)) { 353 | throw new NotFoundHttpException(sprintf('The user with "%s" does not exist for value "%s"', $key, $value)); 354 | } 355 | 356 | return $user; 357 | } 358 | 359 | /** 360 | * Authenticate a user with Symfony Security 361 | * 362 | * @param Boolean $reAuthenticate 363 | * @return null 364 | */ 365 | protected function authenticateUser(UserInterface $user, $reAuthenticate = false) 366 | { 367 | $providerKey = $this->container->getParameter('fos_user.provider_key'); 368 | $token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles()); 369 | 370 | if (true === $reAuthenticate) { 371 | $token->setAuthenticated(false); 372 | } 373 | 374 | $this->container->get('security.context')->setToken($token); 375 | } 376 | 377 | protected function setFlash($action, $value) 378 | { 379 | $this->container->get('session')->setFlash($action, $value); 380 | } 381 | 382 | protected function getPasswordRequestTtl() 383 | { 384 | return $this->container->getParameter('fos_user.email.resetting_password.token_ttl'); 385 | } 386 | 387 | protected function getEngine() 388 | { 389 | return $this->container->getParameter('fos_user.template.engine'); 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class Configuration 17 | { 18 | /** 19 | * Generates the configuration tree. 20 | * 21 | * @return \Symfony\Component\DependencyInjection\Configuration\NodeInterface 22 | */ 23 | public function getConfigTree() 24 | { 25 | $treeBuilder = new TreeBuilder(); 26 | $rootNode = $treeBuilder->root('fos_user', 'array'); 27 | 28 | $rootNode 29 | ->scalarNode('db_driver')->cannotBeOverwritten()->isRequired()->cannotBeEmpty()->end() 30 | ->scalarNode('provider_key')->isRequired()->cannotBeEmpty()->end(); 31 | 32 | $this->addClassSection($rootNode); 33 | $this->addServiceSection($rootNode); 34 | $this->addEncoderSection($rootNode); 35 | $this->addFormNameSection($rootNode); 36 | $this->addFormValidationGroupsSection($rootNode); 37 | $this->addEmailSection($rootNode); 38 | $this->addTemplateSection($rootNode); 39 | 40 | return $treeBuilder->buildTree(); 41 | } 42 | 43 | private function addClassSection(NodeBuilder $node) 44 | { 45 | $node 46 | ->arrayNode('class') 47 | ->isRequired() 48 | ->addDefaultsIfNotSet() 49 | ->arrayNode('model') 50 | ->isRequired() 51 | ->scalarNode('user')->isRequired()->cannotBeEmpty()->end() 52 | ->scalarNode('group')->isRequired()->cannotBeEmpty()->end() 53 | ->end() 54 | ->arrayNode('form') 55 | ->addDefaultsIfNotSet() 56 | ->scalarNode('user')->defaultValue('FOS\\UserBundle\\Form\\UserForm')->end() 57 | ->scalarNode('group')->defaultValue('FOS\\UserBundle\\Form\\GroupForm')->end() 58 | ->scalarNode('change_password')->defaultValue('FOS\\UserBundle\\Form\\ChangePasswordForm')->end() 59 | ->scalarNode('reset_password')->defaultValue('FOS\\UserBundle\\Form\\ResetPasswordForm')->end() 60 | ->end() 61 | ->arrayNode('controller') 62 | ->addDefaultsIfNotSet() 63 | ->scalarNode('user')->defaultValue('FOS\\UserBundle\\Controller\\UserController')->end() 64 | ->scalarNode('group')->defaultValue('FOS\\UserBundle\\Controller\\GroupController')->end() 65 | ->scalarNode('security')->defaultValue('FOS\\UserBundle\\Controller\\SecurityController')->end() 66 | ->end() 67 | ->arrayNode('util') 68 | ->addDefaultsIfNotSet() 69 | ->scalarNode('email_canonicalizer')->defaultValue('FOS\\UserBundle\\Util\\Canonicalizer')->end() 70 | ->scalarNode('username_canonicalizer')->defaultValue('FOS\\UserBundle\\Util\\Canonicalizer')->end() 71 | ->end() 72 | ->end(); 73 | } 74 | 75 | private function addServiceSection(NodeBuilder $node) 76 | { 77 | $node 78 | ->arrayNode('service') 79 | ->arrayNode('util') 80 | ->scalarNode('mailer')->end() 81 | ->end() 82 | ->end(); 83 | } 84 | 85 | private function addEncoderSection(NodeBuilder $node) 86 | { 87 | $node 88 | ->arrayNode('encoder') 89 | ->addDefaultsIfNotSet() 90 | ->scalarNode('algorithm')->defaultValue('sha512')->end() 91 | ->booleanNode('encode_as_base64')->defaultFalse()->end() 92 | ->scalarNode('iterations')->defaultValue(1)->end() 93 | ->end(); 94 | } 95 | 96 | private function addFormNameSection(NodeBuilder $node) 97 | { 98 | $node 99 | ->arrayNode('form_name') 100 | ->addDefaultsIfNotSet() 101 | ->scalarNode('user') 102 | ->defaultValue('fos_user_user_form') 103 | ->cannotBeEmpty() 104 | ->end() 105 | ->scalarNode('group') 106 | ->defaultValue('fos_user_group_form') 107 | ->cannotBeEmpty() 108 | ->end() 109 | ->scalarNode('change_password') 110 | ->defaultValue('fos_user_change_password_form') 111 | ->cannotBeEmpty() 112 | ->end() 113 | ->scalarNode('reset_password') 114 | ->defaultValue('fos_user_reset_password_form') 115 | ->cannotBeEmpty() 116 | ->end() 117 | ->end(); 118 | } 119 | 120 | private function addFormValidationGroupsSection(NodeBuilder $node) 121 | { 122 | $node 123 | ->arrayNode('form_validation_groups') 124 | ->addDefaultsIfNotSet() 125 | ->arrayNode('user') 126 | ->addDefaultsIfNotSet() 127 | ->prototype('scalar')->end() 128 | ->defaultValue(array('Registration')) 129 | ->end() 130 | ->arrayNode('change_password') 131 | ->addDefaultsIfNotSet() 132 | ->prototype('scalar')->end() 133 | ->defaultValue(array('ChangePassword')) 134 | ->end() 135 | ->arrayNode('reset_password') 136 | ->addDefaultsIfNotSet() 137 | ->prototype('scalar')->end() 138 | ->defaultValue(array('ResetPassword')) 139 | ->end() 140 | ->arrayNode('group') 141 | ->addDefaultsIfNotSet() 142 | ->prototype('scalar')->end() 143 | ->defaultValue(array('Registration')) 144 | ->end() 145 | ->end(); 146 | } 147 | 148 | private function addEmailSection(NodeBuilder $node) 149 | { 150 | $node 151 | ->arrayNode('email') 152 | ->addDefaultsIfNotSet() 153 | ->arrayNode('from_email') 154 | ->addDefaultsIfNotSet() 155 | ->useAttributeAsKey('address') 156 | ->prototype('scalar') 157 | ->beforeNormalization() 158 | ->ifTrue(function ($v) { return is_array($v) && isset ($v['name']); }) 159 | ->then(function ($v) { return $v['name']; }) 160 | ->end() 161 | ->end() 162 | ->defaultValue(array('webmaster@example.com' => 'webmaster')) 163 | ->end() 164 | ->arrayNode('confirmation') 165 | ->addDefaultsIfNotSet() 166 | ->booleanNode('enabled')->defaultFalse()->end() 167 | ->scalarNode('template')->defaultValue('FOSUserBundle:User:confirmationEmail')->end() 168 | ->end() 169 | ->arrayNode('resetting_password') 170 | ->addDefaultsIfNotSet() 171 | ->scalarNode('template')->defaultValue('FOSUserBundle:User:resettingPasswordEmail')->end() 172 | ->scalarNode('token_ttl')->defaultValue(86400)->end() 173 | ->end() 174 | ->end(); 175 | } 176 | 177 | private function addTemplateSection(NodeBuilder $node) 178 | { 179 | $node 180 | ->arrayNode('template') 181 | ->addDefaultsIfNotSet() 182 | ->scalarNode('engine')->defaultValue('twig')->end() 183 | ->scalarNode('theme')->defaultValue('TwigBundle::form.html.twig')->end() 184 | ->end(); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /DependencyInjection/FOSUserExtension.php: -------------------------------------------------------------------------------- 1 | process($configuration->getConfigTree(), $configs); 19 | 20 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 21 | 22 | if (!in_array(strtolower($config['db_driver']), array('orm', 'mongodb'))) { 23 | throw new \InvalidArgumentException(sprintf('Invalid db driver "%s".', $config['db_driver'])); 24 | } 25 | $loader->load(sprintf('%s.xml', $config['db_driver'])); 26 | 27 | foreach (array('controller', 'templating', 'twig', 'form', 'validator', 'security', 'util', 'listener') as $basename) { 28 | $loader->load(sprintf('%s.xml', $basename)); 29 | } 30 | 31 | if (!empty($config['service']['util']['mailer'])) { 32 | $container->setAlias('fos_user.util.mailer', $config['service']['util']['mailer']); 33 | } 34 | 35 | $this->remapParametersNamespaces($config, $container, array( 36 | '' => array( 37 | 'provider_key' => 'fos_user.provider_key' 38 | ), 39 | 'encoder' => 'fos_user.encoder.%s', 40 | 'template' => 'fos_user.template.%s', 41 | 'form_name' => 'fos_user.form.%s.name', 42 | 'form_validation_groups' => 'fos_user.form.%s.validation_groups', 43 | )); 44 | 45 | $this->remapParametersNamespaces($config['class'], $container, array( 46 | 'model' => 'fos_user.model.%s.class', 47 | 'form' => 'fos_user.form.%s.class', 48 | 'controller' => 'fos_user.controller.%s.class', 49 | 'util' => 'fos_user.util.%s.class', 50 | )); 51 | 52 | $this->remapParametersNamespaces($config['email'], $container, array( 53 | '' => array('from_email' => 'fos_user.email.from_email'), 54 | 'confirmation' => 'fos_user.email.confirmation.%s', 55 | 'resetting_password' => 'fos_user.email.resetting_password.%s', 56 | )); 57 | } 58 | 59 | protected function remapParameters(array $config, ContainerBuilder $container, array $map) 60 | { 61 | foreach ($map as $name => $paramName) { 62 | if (isset($config[$name])) { 63 | $container->setParameter($paramName, $config[$name]); 64 | } 65 | } 66 | } 67 | 68 | protected function remapParametersNamespaces(array $config, ContainerBuilder $container, array $namespaces) 69 | { 70 | foreach ($namespaces as $ns => $map) { 71 | if ($ns) { 72 | if (!isset($config[$ns])) { 73 | continue; 74 | } 75 | $namespaceConfig = $config[$ns]; 76 | } else { 77 | $namespaceConfig = $config; 78 | } 79 | if (is_array($map)) { 80 | $this->remapParameters($namespaceConfig, $container, $map); 81 | } else { 82 | foreach ($namespaceConfig as $name => $value) { 83 | if (null !== $value) { 84 | $container->setParameter(sprintf($map, $name), $value); 85 | } 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Document/DefaultGroup.php: -------------------------------------------------------------------------------- 1 | dm = $dm; 18 | $this->repository = $dm->getRepository($class); 19 | 20 | $metadata = $dm->getClassMetadata($class); 21 | $this->class = $metadata->name; 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | public function deleteGroup(GroupInterface $group) 28 | { 29 | $this->dm->remove($group); 30 | $this->dm->flush(); 31 | } 32 | 33 | /** 34 | * {@inheritDoc} 35 | */ 36 | public function getClass() 37 | { 38 | return $this->class; 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | */ 44 | public function findGroupBy(array $criteria) 45 | { 46 | return $this->repository->findOneBy($criteria); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | public function findGroups() 53 | { 54 | return $this->repository->findAll(); 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | public function updateGroup(GroupInterface $group) 61 | { 62 | $this->dm->persist($group); 63 | $this->dm->flush(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Document/User.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Thibault Duplessis 6 | * 7 | * This source file is subject to the MIT license that is bundled 8 | * with this source code in the file LICENSE. 9 | */ 10 | 11 | namespace FOS\UserBundle\Document; 12 | 13 | use FOS\UserBundle\Model\User as AbstractUser; 14 | 15 | abstract class User extends AbstractUser 16 | { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Document/UserManager.php: -------------------------------------------------------------------------------- 1 | dm = $dm; 34 | $this->repository = $dm->getRepository($class); 35 | 36 | $metadata = $dm->getClassMetadata($class); 37 | $this->class = $metadata->name; 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | */ 43 | public function deleteUser(UserInterface $user) 44 | { 45 | $this->dm->remove($user); 46 | $this->dm->flush(); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | public function getClass() 53 | { 54 | return $this->class; 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | public function findUserBy(array $criteria) 61 | { 62 | return $this->repository->findOneBy($criteria); 63 | } 64 | 65 | /** 66 | * {@inheritDoc} 67 | */ 68 | public function findUsers() 69 | { 70 | return $this->repository->findAll(); 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | */ 76 | public function updateUser(UserInterface $user) 77 | { 78 | $this->updateCanonicalFields($user); 79 | $this->updatePassword($user); 80 | 81 | $this->dm->persist($user); 82 | $this->dm->flush(); 83 | } 84 | 85 | /** 86 | * {@inheritDoc} 87 | */ 88 | public function validateUnique($value, Constraint $constraint) 89 | { 90 | $classMetadata = $this->dm->getClassMetadata($this->class); 91 | // TODO: ODM seems to be missing handling for multiple properties 92 | // $fields = array_map('trim', explode(',', $constraint->property)); 93 | $query = $this->getQueryArray($classMetadata, $value, $constraint->property); 94 | 95 | $document = $this->findUserBy($query); 96 | if (null === $document) { 97 | return true; 98 | } 99 | 100 | // check if document in mongodb is the same document as the checked one 101 | if ($document->isUser($value)) { 102 | return true; 103 | } 104 | // check if returned document is proxy and initialize the minimum identifier if needed 105 | if ($document instanceof Proxy) { 106 | $classMetadata->setIdentifierValue($document, $document->__identifier); 107 | } 108 | // check if document has the same identifier as the current one 109 | if ($classMetadata->getIdentifierValue($document) === $classMetadata->getIdentifierValue($value)) { 110 | return true; 111 | } 112 | 113 | return false; 114 | } 115 | 116 | protected function getQueryArray($classMetadata, $value, $fieldName) 117 | { 118 | $field = $this->getFieldNameFromPropertyPath($fieldName); 119 | if (!isset($classMetadata->fieldMappings[$field])) { 120 | throw new \LogicException("Mapping for '$fieldName' doesn't exist for " . $this->class); 121 | } 122 | 123 | $mapping = $classMetadata->fieldMappings[$field]; 124 | if (isset($mapping['reference']) && $mapping['reference']) { 125 | throw new \LogicException('Cannot determine uniqueness of referenced document values'); 126 | } 127 | 128 | $criteria[$field] = $value instanceOf UserInterface ? $classMetadata->getFieldValue($value, $field) : $value; 129 | 130 | return $criteria; 131 | } 132 | 133 | /** 134 | * Returns the actual document field value 135 | * 136 | * E.g. document.someVal -> document 137 | * user.emails -> user 138 | * username -> username 139 | * 140 | * @param string $field 141 | * @return string 142 | */ 143 | protected function getFieldNameFromPropertyPath($field) 144 | { 145 | $pieces = explode('.', $field); 146 | return $pieces[0]; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Entity/DefaultGroup.php: -------------------------------------------------------------------------------- 1 | em = $em; 18 | $this->repository = $em->getRepository($class); 19 | 20 | $metadata = $em->getClassMetadata($class); 21 | $this->class = $metadata->name; 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | public function deleteGroup(GroupInterface $group) 28 | { 29 | $this->em->remove($group); 30 | $this->em->flush(); 31 | } 32 | 33 | /** 34 | * {@inheritDoc} 35 | */ 36 | public function getClass() 37 | { 38 | return $this->class; 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | */ 44 | public function findGroupBy(array $criteria) 45 | { 46 | return $this->repository->findOneBy($criteria); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | public function findGroups() 53 | { 54 | return $this->repository->findAll(); 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | public function updateGroup(GroupInterface $group) 61 | { 62 | $this->em->persist($group); 63 | $this->em->flush(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Entity/User.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Thibault Duplessis 6 | * 7 | * This source file is subject to the MIT license that is bundled 8 | * with this source code in the file LICENSE. 9 | */ 10 | 11 | namespace FOS\UserBundle\Entity; 12 | 13 | use FOS\UserBundle\Model\User as AbstractUser; 14 | 15 | abstract class User extends AbstractUser 16 | { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Entity/UserManager.php: -------------------------------------------------------------------------------- 1 | em = $em; 33 | $this->repository = $em->getRepository($class); 34 | 35 | $metadata = $em->getClassMetadata($class); 36 | $this->class = $metadata->name; 37 | } 38 | 39 | /** 40 | * {@inheritDoc} 41 | */ 42 | public function deleteUser(UserInterface $user) 43 | { 44 | $this->em->remove($user); 45 | $this->em->flush(); 46 | } 47 | 48 | /** 49 | * {@inheritDoc} 50 | */ 51 | public function getClass() 52 | { 53 | return $this->class; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | public function findUserBy(array $criteria) 60 | { 61 | return $this->repository->findOneBy($criteria); 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | */ 67 | public function findUsers() 68 | { 69 | return $this->repository->findAll(); 70 | } 71 | 72 | /** 73 | * {@inheritDoc} 74 | */ 75 | public function updateUser(UserInterface $user) 76 | { 77 | $this->updateCanonicalFields($user); 78 | $this->updatePassword($user); 79 | 80 | $this->em->persist($user); 81 | $this->em->flush(); 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | */ 87 | public function validateUnique($value, Constraint $constraint) 88 | { 89 | $fields = array_map('trim', explode(',', $constraint->property)); 90 | $users = $this->findConflictualUsers($value, $fields); 91 | 92 | // there is no conflictual user 93 | if (empty($users)) { 94 | return true; 95 | } 96 | 97 | // there is no conflictual user which is not the same as the value 98 | if ($this->anyIsUser($value, $users)) { 99 | return true; 100 | } 101 | 102 | return false; 103 | } 104 | 105 | /** 106 | * Indicates whether the given user and all compared objects correspond to the same record 107 | * 108 | * @param UserInterface $user 109 | * @param array $comparisons 110 | * @return boolean 111 | */ 112 | protected function anyIsUser($user, array $comparisons) 113 | { 114 | foreach ($comparisons as $comparison) { 115 | if (!$user->isUser($comparison)) { 116 | return false; 117 | } 118 | } 119 | 120 | return true; 121 | } 122 | 123 | /** 124 | * Gets conflictual users for the given user and constraint 125 | * 126 | * @param UserInterface $value 127 | * @param array $fields 128 | * @return array 129 | */ 130 | protected function findConflictualUsers($value, array $fields) 131 | { 132 | return $this->repository->findBy($this->getCriteria($value, $fields)); 133 | } 134 | 135 | /** 136 | * Gets the criteria used to find conflictual entities 137 | * 138 | * @param UserInterface $value 139 | * @param array $constraint 140 | * @return array 141 | */ 142 | protected function getCriteria($value, array $fields) 143 | { 144 | $classMetadata = $this->em->getClassMetadata($this->class); 145 | 146 | $criteria = array(); 147 | foreach ($fields as $field) { 148 | if (!$classMetadata->hasField($field)) { 149 | throw new \InvalidArgumentException(sprintf('The "%s" class metadata does not have any "%s" field or association mapping.', $this->class, $field)); 150 | } 151 | 152 | $criteria[$field] = $classMetadata->getFieldValue($value, $field); 153 | } 154 | 155 | return $criteria; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /FOSUserBundle.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Thibault Duplessis 6 | * 7 | * This source file is subject to the MIT license that is bundled 8 | * with this source code in the file LICENSE. 9 | */ 10 | 11 | namespace FOS\UserBundle; 12 | 13 | use Symfony\Component\HttpKernel\Bundle\Bundle; 14 | 15 | class FOSUserBundle extends Bundle 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /Form/ChangePassword.php: -------------------------------------------------------------------------------- 1 | add(new PasswordField('current')); 18 | parent::configure(); 19 | } 20 | 21 | public function process(UserInterface $user) 22 | { 23 | $this->setData(new ChangePassword($user)); 24 | 25 | if ('POST' == $this->request->getMethod()) { 26 | $this->bind($this->request); 27 | 28 | if ($this->isValid()) { 29 | $user->setPlainPassword($this->getNewPassword()); 30 | $this->userManager->updateUser($user); 31 | 32 | return true; 33 | } 34 | } 35 | 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Form/GroupForm.php: -------------------------------------------------------------------------------- 1 | addOption('theme'); 31 | 32 | parent::__construct($name, $options); 33 | } 34 | 35 | public function setRequest(Request $request) 36 | { 37 | $this->request = $request; 38 | } 39 | 40 | public function setGroupManager(GroupManagerInterface $groupManager) 41 | { 42 | $this->groupManager = $groupManager; 43 | } 44 | 45 | public function configure() 46 | { 47 | $this->add(new TextField('name')); 48 | } 49 | 50 | public function process(GroupInterface $group = null) 51 | { 52 | if (null === $group) { 53 | $group = $this->groupManager->createGroup(''); 54 | } 55 | 56 | $this->setData($group); 57 | 58 | if ('POST' == $this->request->getMethod()) { 59 | $this->bind($this->request); 60 | 61 | if ($this->isValid()) { 62 | $this->groupManager->updateGroup($group); 63 | return true; 64 | } 65 | } 66 | 67 | return false; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Form/ResetPassword.php: -------------------------------------------------------------------------------- 1 | user = $user; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Form/ResetPasswordForm.php: -------------------------------------------------------------------------------- 1 | addOption('theme'); 32 | 33 | parent::__construct($name, $options); 34 | } 35 | 36 | public function setRequest(Request $request) 37 | { 38 | $this->request = $request; 39 | } 40 | 41 | public function setUserManager(UserManagerInterface $userManager) 42 | { 43 | $this->userManager = $userManager; 44 | } 45 | 46 | public function configure() 47 | { 48 | $this->add(new RepeatedField(new PasswordField('new'))); 49 | } 50 | 51 | public function getNewPassword() 52 | { 53 | return $this->getData()->new; 54 | } 55 | 56 | public function process(UserInterface $user) 57 | { 58 | $this->setData(new ResetPassword($user)); 59 | 60 | if ('POST' == $this->request->getMethod()) { 61 | $this->bind($this->request); 62 | 63 | if ($this->isValid()) { 64 | $user->setPlainPassword($this->getNewPassword()); 65 | $user->setConfirmationToken(null); 66 | $user->setEnabled(true); 67 | $this->userManager->updateUser($user); 68 | 69 | return true; 70 | } 71 | } 72 | 73 | return false; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Form/UserForm.php: -------------------------------------------------------------------------------- 1 | addOption('theme'); 30 | 31 | parent::__construct($title, $options); 32 | } 33 | 34 | public function setRequest(Request $request) 35 | { 36 | $this->request = $request; 37 | } 38 | 39 | public function setUserManager(UserManagerInterface $userManager) 40 | { 41 | $this->userManager = $userManager; 42 | } 43 | 44 | public function configure() 45 | { 46 | $this->add(new TextField('username')); 47 | $this->add(new TextField('email')); 48 | $this->add(new RepeatedField(new PasswordField('plainPassword'))); 49 | } 50 | 51 | public function bind(Request $request, $data = null) 52 | { 53 | if (!$this->getName()) { 54 | throw new FormException('You cannot bind anonymous forms. Please give this form a name'); 55 | } 56 | 57 | // Store object from which to read the default values and where to 58 | // write the submitted values 59 | if (null !== $data) { 60 | $this->setData($data); 61 | } 62 | 63 | // Store the submitted data in case of a post request 64 | if ('POST' == $request->getMethod()) { 65 | $values = $request->request->get($this->getName(), array()); 66 | $files = $request->files->get($this->getName(), array()); 67 | 68 | $this->submit(self::deepArrayUnion($values, $files)); 69 | 70 | $this->userManager->updateCanonicalFields($this->getData()); 71 | 72 | $this->validate(); 73 | } 74 | } 75 | 76 | public function process(UserInterface $user = null, $confirmation = null) 77 | { 78 | if (null === $user) { 79 | $user = $this->userManager->createUser(); 80 | } 81 | 82 | $this->setData($user); 83 | 84 | if ('POST' == $this->request->getMethod()) { 85 | $this->bind($this->request); 86 | 87 | if ($this->isValid()) { 88 | if (true === $confirmation) { 89 | $user->setEnabled(false); 90 | } else if (false === $confirmation) { 91 | $user->setConfirmationToken(null); 92 | $user->setEnabled(true); 93 | } 94 | 95 | $this->userManager->updateUser($user); 96 | 97 | return true; 98 | } 99 | } 100 | 101 | return false; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Model/Group.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * This source file is subject to the MIT license that is bundled 7 | * with this source code in the file LICENSE. 8 | */ 9 | 10 | namespace FOS\UserBundle\Model; 11 | 12 | abstract class Group implements GroupInterface 13 | { 14 | protected $id; 15 | protected $name; 16 | protected $roles; 17 | 18 | public function __construct($name, $roles = array()) 19 | { 20 | $this->name = $name; 21 | $this->roles = $roles; 22 | } 23 | 24 | public function addRole($role) 25 | { 26 | if (!$this->hasRole($role)) { 27 | $this->roles[] = strtoupper($role); 28 | } 29 | } 30 | 31 | public function getId() 32 | { 33 | return $this->id; 34 | } 35 | 36 | public function getName() 37 | { 38 | return $this->name; 39 | } 40 | 41 | public function hasRole($role) 42 | { 43 | return in_array(strtoupper($role), $this->roles, true); 44 | } 45 | 46 | public function getRoles() 47 | { 48 | return $this->roles; 49 | } 50 | 51 | public function removeRole($role) 52 | { 53 | if (false !== $key = array_search(strtoupper($role), $this->roles, true)) { 54 | unset($this->roles[$key]); 55 | $this->roles = array_values($this->roles); 56 | } 57 | } 58 | 59 | public function setName($name) 60 | { 61 | $this->name = $name; 62 | } 63 | 64 | public function setRoles(array $roles) 65 | { 66 | $this->roles = $roles; 67 | } 68 | } -------------------------------------------------------------------------------- /Model/GroupInterface.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Christophe Coevoet 6 | * 7 | * This source file is subject to the MIT license that is bundled 8 | * with this source code in the file LICENSE. 9 | */ 10 | 11 | namespace FOS\UserBundle\Model; 12 | 13 | interface GroupInterface 14 | { 15 | function addRole($role); 16 | 17 | function getId(); 18 | 19 | function getName(); 20 | 21 | function hasRole($role); 22 | 23 | function getRoles(); 24 | 25 | function removeRole($role); 26 | 27 | function setName($name); 28 | 29 | function setRoles(array $roles); 30 | } -------------------------------------------------------------------------------- /Model/GroupManager.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | abstract class GroupManager implements GroupManagerInterface 12 | { 13 | /** 14 | * Returns an empty group instance 15 | * 16 | * @param string $name 17 | * @return Group 18 | */ 19 | public function createGroup($name) 20 | { 21 | $class = $this->getClass(); 22 | 23 | return new $class($name); 24 | } 25 | /** 26 | * Finds a group by name 27 | * 28 | * @param string $name 29 | * @return GroupInterface 30 | */ 31 | public function findGroupByName($name) 32 | { 33 | return $this->findGroupBy(array('name' => $name)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Model/GroupManagerInterface.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * This source file is subject to the MIT license that is bundled 7 | * with this source code in the file LICENSE. 8 | */ 9 | 10 | namespace FOS\UserBundle\Model; 11 | 12 | /** 13 | * Interface to be implemented by group managers. This adds an additional level 14 | * of abstraction between your application, and the actual repository. 15 | * 16 | * All changes to groups should happen through this interface. 17 | * 18 | * @author Christophe Coevoet 19 | */ 20 | interface GroupManagerInterface 21 | { 22 | /** 23 | * Returns an empty group instance 24 | * 25 | * @param string $name 26 | * @return GroupInterface 27 | */ 28 | function createGroup($name); 29 | 30 | /** 31 | * Deletes a group 32 | * 33 | * @param GroupInterface $group 34 | * @return void 35 | */ 36 | function deleteGroup(GroupInterface $group); 37 | 38 | /** 39 | * Finds one group by the given criteria 40 | * 41 | * @param array $criteria 42 | * @return GroupInterface 43 | */ 44 | function findGroupBy(array $criteria); 45 | 46 | /** 47 | * Finds a group by name 48 | * 49 | * @param string $name 50 | * @return GroupInterface 51 | */ 52 | function findGroupByName($name); 53 | 54 | /** 55 | * Returns a collection with all user instances 56 | * 57 | * @return Traversable 58 | */ 59 | function findGroups(); 60 | 61 | /** 62 | * Returns the group's fully qualified class name 63 | * 64 | * @return string 65 | */ 66 | function getClass(); 67 | 68 | /** 69 | * Updates a group 70 | * 71 | * @param GroupInterface $group 72 | * @return void 73 | */ 74 | function updateGroup(GroupInterface $group); 75 | } 76 | -------------------------------------------------------------------------------- /Model/UserInterface.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Johannes M. Schmitt 6 | * 7 | * This source file is subject to the MIT license that is bundled 8 | * with this source code in the file LICENSE. 9 | */ 10 | 11 | namespace FOS\UserBundle\Model; 12 | 13 | use Symfony\Component\Security\Core\User\AdvancedAccountInterface; 14 | 15 | interface UserInterface extends AdvancedAccountInterface 16 | { 17 | function addRole($role); 18 | 19 | function getAlgorithm(); 20 | 21 | function setAlgorithm($algorithm); 22 | 23 | function setUsername($username); 24 | 25 | function getUsernameCanonical(); 26 | 27 | function setUsernameCanonical($usernameCanonical); 28 | 29 | function getEmail(); 30 | 31 | function setEmail($email); 32 | 33 | function getEmailCanonical(); 34 | 35 | function setEmailCanonical($emailCanonical); 36 | 37 | function getPlainPassword(); 38 | 39 | function setPlainPassword($password); 40 | 41 | function setPassword($password); 42 | 43 | function isSuperAdmin(); 44 | 45 | function isUser(UserInterface $user = null); 46 | 47 | function setEnabled($boolean); 48 | 49 | function setSuperAdmin($boolean); 50 | 51 | function getConfirmationToken(); 52 | 53 | function setConfirmationToken($confirmationToken); 54 | 55 | function hasRole($role); 56 | 57 | function setRoles(array $roles); 58 | 59 | function removeRole($role); 60 | 61 | function getGroups(); 62 | 63 | function getGroupNames(); 64 | 65 | function hasGroup($name); 66 | 67 | function addGroup(GroupInterface $group); 68 | 69 | function removeGroup(GroupInterface $group); 70 | } 71 | -------------------------------------------------------------------------------- /Model/UserManager.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | abstract class UserManager implements UserManagerInterface, UserProviderInterface 19 | { 20 | protected $encoderFactory; 21 | protected $algorithm; 22 | protected $usernameCanonicalizer; 23 | protected $emailCanonicalizer; 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param EncoderFactoryInterface $encoderFactory 29 | * @param string $algorithm 30 | * @param CanonicalizerInterface $usernameCanonicalizer 31 | * @param CanonicalizerInterface $emailCanonicalizer 32 | */ 33 | public function __construct(EncoderFactoryInterface $encoderFactory, $algorithm, CanonicalizerInterface $usernameCanonicalizer, CanonicalizerInterface $emailCanonicalizer) 34 | { 35 | $this->encoderFactory = $encoderFactory; 36 | $this->algorithm = $algorithm; 37 | $this->usernameCanonicalizer = $usernameCanonicalizer; 38 | $this->emailCanonicalizer = $emailCanonicalizer; 39 | } 40 | 41 | /** 42 | * Returns an empty user instance 43 | * 44 | * @return User 45 | */ 46 | public function createUser() 47 | { 48 | $class = $this->getClass(); 49 | $user = new $class; 50 | $user->setAlgorithm($this->algorithm); 51 | 52 | return $user; 53 | } 54 | 55 | /** 56 | * Finds a user by email 57 | * 58 | * @param string $email 59 | * @return User 60 | */ 61 | public function findUserByEmail($email) 62 | { 63 | return $this->findUserBy(array('emailCanonical' => $this->emailCanonicalizer->canonicalize($email))); 64 | } 65 | 66 | /** 67 | * Finds a user by username 68 | * 69 | * @param string $username 70 | * @return User 71 | */ 72 | public function findUserByUsername($username) 73 | { 74 | return $this->findUserBy(array('usernameCanonical' => $this->usernameCanonicalizer->canonicalize($username))); 75 | } 76 | 77 | /** 78 | * Finds a user either by email, or username 79 | * 80 | * @param string $usernameOrEmail 81 | * @return User 82 | */ 83 | public function findUserByUsernameOrEmail($usernameOrEmail) 84 | { 85 | if (filter_var($usernameOrEmail, FILTER_VALIDATE_EMAIL)) { 86 | return $this->findUserByEmail($usernameOrEmail); 87 | } 88 | 89 | return $this->findUserByUsername($usernameOrEmail); 90 | } 91 | 92 | public function findUserByConfirmationToken($token) 93 | { 94 | return $this->findUserBy(array('confirmationToken' => $token)); 95 | } 96 | 97 | /** 98 | * Finds a user by account 99 | * 100 | * It is strongly discouraged to use this method manually as it bypasses 101 | * all ACL checks. 102 | * 103 | * @param AccountInterface $user 104 | * @return User 105 | */ 106 | public function loadUserByAccount(AccountInterface $user) 107 | { 108 | if (!$user instanceof User) { 109 | throw new UnsupportedAccountException('Account is not supported.'); 110 | } 111 | 112 | return $this->loadUserByUsername($user->getUsername()); 113 | } 114 | 115 | /** 116 | * Loads a user by username 117 | * 118 | * It is strongly discouraged to call this method manually as it bypasses 119 | * all ACL checks. 120 | * 121 | * @RunAs(roles="ROLE_SUPERADMIN") 122 | * @param string $username 123 | * @return AccountInterface 124 | */ 125 | public function loadUserByUsername($username) 126 | { 127 | $user = $this->findUserByUsername($username); 128 | 129 | if (!$user) { 130 | throw new UsernameNotFoundException(sprintf('No user with name "%s" was found.', $username)); 131 | } 132 | 133 | return $user; 134 | } 135 | 136 | /** 137 | * {@inheritDoc} 138 | */ 139 | public function updateCanonicalFields(UserInterface $user) 140 | { 141 | $user->setUsernameCanonical($this->usernameCanonicalizer->canonicalize($user->getUsername())); 142 | $user->setEmailCanonical($this->emailCanonicalizer->canonicalize($user->getEmail())); 143 | } 144 | 145 | /** 146 | * {@inheritDoc} 147 | */ 148 | public function updatePassword(UserInterface $user) 149 | { 150 | if (0 !== strlen($password = $user->getPlainPassword())) { 151 | $user->setAlgorithm($this->algorithm); 152 | $encoder = $this->getEncoder($user); 153 | $user->setPassword($encoder->encodePassword($password, $user->getSalt())); 154 | $user->eraseCredentials(); 155 | } 156 | } 157 | 158 | protected function getEncoder(UserInterface $user) 159 | { 160 | return $this->encoderFactory->getEncoder($user); 161 | } 162 | 163 | /** 164 | * {@inheritDoc} 165 | */ 166 | public function supportsClass($class) 167 | { 168 | return $class === $this->getClass(); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /Model/UserManagerInterface.php: -------------------------------------------------------------------------------- 1 | 5 | * (c) Thibault Duplessis 6 | * (c) Johannes M. Schmitt 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace FOS\UserBundle\Model; 13 | 14 | use Symfony\Component\Validator\Constraint; 15 | 16 | /** 17 | * Interface to be implemented by user managers. This adds an additional level 18 | * of abstraction between your application, and the actual repository. 19 | * 20 | * All changes to users should happen through this interface. 21 | * 22 | * The class also contains ACL annotations which will only work if you have the 23 | * SecurityExtraBundle installed, otherwise they will simply be ignored. 24 | * 25 | * @author Gordon Franke 26 | * @author Thibault Duplessis 27 | * @author Johannes M. Schmitt 28 | */ 29 | interface UserManagerInterface 30 | { 31 | /** 32 | * Creates an empty user instance 33 | * 34 | * @return User 35 | */ 36 | function createUser(); 37 | 38 | /** 39 | * Deletes a user 40 | * 41 | * @SecureParam(name="user", permissions="DELETE") 42 | * @param User $user 43 | * @return void 44 | */ 45 | function deleteUser(UserInterface $user); 46 | 47 | /** 48 | * Finds one user by the given criteria 49 | * 50 | * @SecureReturn(permissions="VIEW") 51 | * @param array $criteria 52 | * @return User 53 | */ 54 | function findUserBy(array $criteria); 55 | 56 | /** 57 | * Find a user by its username 58 | * @param string $username 59 | * @return User or null if user does not exist 60 | */ 61 | function findUserByUsername($username); 62 | 63 | /** 64 | * Find a user by its email 65 | * @param string $email 66 | * @return User or null if user does not exist 67 | */ 68 | function findUserByEmail($email); 69 | 70 | /** 71 | * Find a user by its username or email 72 | * @param string $usernameOrEmail 73 | * @return User or null if user does not exist 74 | */ 75 | function findUserByUsernameOrEmail($usernameOrEmail); 76 | 77 | /** 78 | * Find a user by its confirmationToken 79 | * @param string $token 80 | * @return User or null if user does not exist 81 | */ 82 | function findUserByConfirmationToken($token); 83 | 84 | /** 85 | * Returns a collection with all user instances 86 | * 87 | * @return Traversable 88 | */ 89 | function findUsers(); 90 | 91 | /** 92 | * Returns the user's fully qualified class name 93 | * 94 | * @return string 95 | */ 96 | function getClass(); 97 | 98 | /** 99 | * Updates a user 100 | * 101 | * @SecureParam(name="user", permissions="EDIT") 102 | * @param User $user 103 | * @return void 104 | */ 105 | function updateUser(UserInterface $user); 106 | 107 | /** 108 | * Updates the canonical username and email fields for a user 109 | * 110 | * @SecureParam(name="user", permissions="EDIT") 111 | * @param User $user 112 | * @return void 113 | */ 114 | function updateCanonicalFields(UserInterface $user); 115 | 116 | /** 117 | * Updates a user password if a plain password is set 118 | * 119 | * @SecureParam(name="user", permissions="EDIT") 120 | * @param User $user 121 | * @return void 122 | */ 123 | function updatePassword(UserInterface $user); 124 | 125 | /** 126 | * Checks the uniqueness of the given fields, returns true if its unique 127 | * 128 | * @param UserInterface $value 129 | * @param Constraint $constraint 130 | * @return boolean 131 | */ 132 | function validateUnique($value, Constraint $constraint); 133 | } 134 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | The development has **moved to a [new repository](https://github.com/FriendsOfSymfony/FOSUserBundle)**. 2 | 3 | Please update your submodules. 4 | -------------------------------------------------------------------------------- /Resources/config/controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Resources/config/doctrine/metadata/mongodb/FOS.UserBundle.Document.DefaultGroup.dcm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Resources/config/doctrine/metadata/mongodb/FOS.UserBundle.Document.Group.dcm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Resources/config/doctrine/metadata/mongodb/FOS.UserBundle.Document.User.dcm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Resources/config/doctrine/metadata/orm/FOS.UserBundle.Entity.DefaultGroup.dcm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Resources/config/doctrine/metadata/orm/FOS.UserBundle.Entity.Group.dcm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Resources/config/doctrine/metadata/orm/FOS.UserBundle.Entity.User.dcm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Resources/config/form.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | %fos_user.form.user.name% 12 | 13 | %fos_user.template.theme% 14 | %fos_user.form.user.validation_groups% 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | %fos_user.form.change_password.name% 27 | 28 | %fos_user.template.theme% 29 | %fos_user.form.change_password.validation_groups% 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | %fos_user.form.reset_password.name% 42 | 43 | %fos_user.template.theme% 44 | %fos_user.form.reset_password.validation_groups% 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | %fos_user.form.group.name% 57 | 58 | %fos_user.template.theme% 59 | %fos_user.form.group.validation_groups% 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /Resources/config/listener.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Security\InteractiveLoginListener 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Resources/config/mongodb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Document\UserManager 9 | FOS\UserBundle\Document\GroupManager 10 | 11 | 12 | 13 | 14 | 15 | %fos_user.encoder.algorithm% 16 | 17 | 18 | 19 | %fos_user.model.user.class% 20 | 21 | 22 | 23 | %fos_user.model.group.class% 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Resources/config/orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Entity\UserManager 9 | FOS\UserBundle\Entity\GroupManager 10 | 11 | 12 | 13 | 14 | 15 | %fos_user.encoder.algorithm% 16 | 17 | 18 | 19 | %fos_user.model.user.class% 20 | 21 | 22 | 23 | %fos_user.model.group.class% 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Resources/config/routing/group.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | fos_user.controller.group:listAction 9 | GET 10 | 11 | 12 | 13 | fos_user.controller.group:newAction 14 | GET 15 | 16 | 17 | 18 | fos_user.controller.group:createAction 19 | POST 20 | 21 | 22 | 23 | fos_user.controller.group:showAction 24 | GET 25 | 26 | 27 | 28 | fos_user.controller.group:editAction 29 | GET 30 | 31 | 32 | 33 | fos_user.controller.group:updateAction 34 | POST 35 | 36 | 37 | 38 | fos_user.controller.group:deleteAction 39 | GET 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Resources/config/routing/security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | fos_user.controller.security:loginAction 9 | 10 | 11 | 12 | fos_user.controller.security:loginAction 13 | 14 | 15 | 16 | fos_user.controller.security:logoutAction 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Resources/config/routing/user.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | fos_user.controller.user:listAction 9 | GET 10 | 11 | 12 | 13 | fos_user.controller.user:newAction 14 | GET 15 | 16 | 17 | 18 | fos_user.controller.user:createAction 19 | POST 20 | 21 | 22 | 23 | fos_user.controller.user:checkConfirmationEmailAction 24 | GET 25 | 26 | 27 | 28 | fos_user.controller.user:confirmAction 29 | GET 30 | 31 | 32 | 33 | fos_user.controller.user:confirmedAction 34 | GET 35 | 36 | 37 | 38 | fos_user.controller.user:changePasswordAction 39 | GET 40 | 41 | 42 | 43 | fos_user.controller.user:changePasswordUpdateAction 44 | POST 45 | 46 | 47 | 48 | fos_user.controller.user:requestResetPasswordAction 49 | GET 50 | 51 | 52 | 53 | fos_user.controller.user:sendResettingEmailAction 54 | POST 55 | 56 | 57 | 58 | fos_user.controller.user:checkResettingEmailAction 59 | GET 60 | 61 | 62 | 63 | fos_user.controller.user:resetPasswordAction 64 | GET 65 | 66 | 67 | 68 | fos_user.controller.user:resetPasswordUpdateAction 69 | POST 70 | 71 | 72 | 73 | fos_user.controller.user:showAction 74 | GET 75 | 76 | 77 | 78 | fos_user.controller.user:editAction 79 | GET 80 | 81 | 82 | 83 | fos_user.controller.user:updateAction 84 | POST 85 | 86 | 87 | 88 | fos_user.controller.user:deleteAction 89 | GET 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Resources/config/security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Security\Encoder\EncoderFactory 9 | 10 | 11 | 12 | 13 | %security.encoder.digest.class% 14 | %fos_user.encoder.encode_as_base64% 15 | %fos_user.encoder.iterations% 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Resources/config/templating.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Templating\Helper\SecurityHelper 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Resources/config/twig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Twig\UserExtension 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Resources/config/util.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | %fos_user.email.confirmation.template% 17 | %fos_user.email.resetting_password.template% 18 | 19 | %fos_user.email.from_email% 20 | %fos_user.email.from_email% 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Resources/config/validation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Resources/config/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOS\UserBundle\Validator\PasswordValidator 9 | FOS\UserBundle\Validator\UniqueValidator 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Resources/doc/index.rst: -------------------------------------------------------------------------------- 1 | Provides user persistence for your Symfony2 Project. 2 | 3 | Features 4 | ======== 5 | 6 | - Compatible with Doctrine ORM **and** ODM thanks to a generic repository. 7 | - Model is extensible at will 8 | - REST-ful authentication 9 | - Current user available in your controllers and views 10 | - Unit tested and functionally tested 11 | 12 | Installation 13 | ============ 14 | 15 | Add UserBundle to your src/ dir 16 | ------------------------------------- 17 | 18 | :: 19 | 20 | $ git submodule add git://github.com/FriendsOfSymfony/UserBundle.git src/FOS/UserBundle 21 | 22 | Add the FOS namespace to your autoloader 23 | ---------------------------------------- 24 | 25 | :: 26 | // app/autoload.php 27 | $loader->registerNamespaces(array( 28 | 'FOS' => __DIR__.'/../src', 29 | // your other namespaces 30 | ); 31 | 32 | Add UserBundle to your application kernel 33 | ----------------------------------------- 34 | 35 | :: 36 | 37 | // app/AppKernel.php 38 | 39 | public function registerBundles() 40 | { 41 | return array( 42 | // ... 43 | new FOS\UserBundle\FOSUserBundle(), 44 | // ... 45 | ); 46 | } 47 | 48 | Create your User class 49 | ---------------------- 50 | 51 | You must create a User class that extends either the entity or document abstract 52 | User class in UserBundle. All fields on the base class are mapped, except for 53 | ``id`` and ``groups``; this is intentional, so you can select the generator that 54 | best suits your application, and are able to use a custom Group model class. 55 | Feel free to add additional properties and methods to your custom class. 56 | 57 | ORM User class: 58 | ~~~~~~~~~~~~~~~ 59 | 60 | :: 61 | 62 | // src/MyProject/MyBundle/Entity/User.php 63 | 64 | namespace MyProject\MyBundle\Entity; 65 | use FOS\UserBundle\Entity\User as BaseUser; 66 | 67 | /** 68 | * @orm:Entity 69 | */ 70 | class User extends BaseUser 71 | { 72 | /** 73 | * @orm:Id 74 | * @orm:Column(type="integer") 75 | * @orm:generatedValue(strategy="AUTO") 76 | */ 77 | protected $id; 78 | 79 | /** 80 | * @orm:ManyToMany(targetEntity="FOS\UserBundle\Entity\DefaultGroup") 81 | * @orm:JoinTable(name="fos_user_user_group", 82 | * joinColumns={@orm:JoinColumn(name="user_id", referencedColumnName="id")}, 83 | * inverseJoinColumns={@orm:JoinColumn(name="group_id", referencedColumnName="id")} 84 | * ) 85 | */ 86 | protected $groups; 87 | } 88 | 89 | MongoDB User class: 90 | ~~~~~~~~~~~~~~~~~~~ 91 | 92 | :: 93 | 94 | // src/MyProject/MyBundle/Document/User.php 95 | 96 | namespace MyProject\MyBundle\Document; 97 | use FOS\UserBundle\Document\User as BaseUser; 98 | 99 | /** 100 | * @mongodb:Document 101 | */ 102 | class User extends BaseUser 103 | { 104 | /** @mongodb:Id(strategy="auto") */ 105 | protected $id; 106 | 107 | /** @mongodb:ReferenceMany(targetDocument="FOS\UserBundle\Document\DefaultGroup") */ 108 | protected $groups; 109 | } 110 | 111 | Group class 112 | ----------- 113 | 114 | To customize the Group class you can define your own entity extending the mapped 115 | superclass of the Bundle ``FOS\UserBundle\Entity\Group``. If you don't want to 116 | extend it you can use the entity provided by the bundle which is 117 | ``FOS\UserBundle\Entity\DefaultGroup``. 118 | Same is available for MongoDB in the ``Document`` subnamespace. 119 | 120 | Configure your project 121 | ---------------------- 122 | 123 | The UserBundle works with the Symfony Security Component, so make sure that is 124 | enabled in your kernel and in your project's configuration:: 125 | 126 | // app/AppKernel.php 127 | public function registerBundles() 128 | { 129 | return array( 130 | // ... 131 | new Symfony\Bundle\SecurityBundle\SecurityBundle(), 132 | // ... 133 | ); 134 | } 135 | 136 | # app/config/config.yml 137 | security: 138 | providers: 139 | fos_user: 140 | id: fos_user.user_manager 141 | 142 | Note:: 143 | 144 | You need to activate SwiftmailerBundle to be able to use the functionalities 145 | using emails (confirmation of the account, resetting of the password). 146 | See the `Emails` section to know how using another mailer. 147 | 148 | The login form and all the routes used to create a user and reset the password 149 | have to be available to unauthenticated users but using the same firewall as 150 | the pages you want to securize with the bundle. Assuming you import the 151 | user.xml routing file with the ``/user`` prefix they will be:: 152 | 153 | /login 154 | /user/new 155 | /user/check-confirmation-email 156 | /user/confirm/{token} 157 | /user/confirmed 158 | /user/request-reset-password 159 | /user/send-resetting-email 160 | /user/check-resetting-email 161 | /user/reset-password/{token} 162 | 163 | You also have to include the UserBundle in your Doctrine mapping configuration, 164 | along with the bundle containing your custom User class:: 165 | 166 | # app/config/config.yml 167 | doctrine: 168 | orm: 169 | mappings: 170 | FOSUserBundle: ~ 171 | MyProjectMyBundle: ~ 172 | # your other bundles 173 | 174 | The above example assumes an ORM configuration, but the `mappings` configuration 175 | block would be the same for MongoDB ODM. 176 | 177 | Minimal configuration 178 | --------------------- 179 | 180 | At a minimum, your configuration must define your DB driver ("orm" or "mongodb"), 181 | a User class and the provider key. The provider key matches the key in the firewall 182 | configuration that is used for users with the UserController. 183 | 184 | For example for a security configuration like the following the provider_key would 185 | have to be set to "fos_userbundle", as shown in the proceeding examples: 186 | 187 | :: 188 | 189 | # app/config/config.yml 190 | security: 191 | providers: 192 | fos_userbundle: 193 | id: fos_user.user_manager 194 | 195 | firewalls: 196 | main: 197 | form_login: 198 | provider: fos_userbundle 199 | 200 | ORM 201 | ~~~ 202 | 203 | In YAML: 204 | 205 | :: 206 | 207 | # app/config/config.yml 208 | fos_user: 209 | db_driver: orm 210 | provider_key: fos_userbundle 211 | class: 212 | model: 213 | user: MyProject\MyBundle\Entity\User 214 | group: FOS\UserBundle\Entity\DefaultGroup 215 | 216 | Or if you prefer XML: 217 | 218 | :: 219 | 220 | # app/config/config.xml 221 | 222 | 223 | 224 | 228 | 229 | 230 | 231 | ODM 232 | ~~~ 233 | 234 | In YAML: 235 | 236 | :: 237 | 238 | # app/config/config.yml 239 | fos_user: 240 | db_driver: mongodb 241 | provider_key: fos_userbundle 242 | class: 243 | model: 244 | user: MyProject\MyBundle\Document\User 245 | group: FOS\UserBundle\Document\DefaultGroup 246 | 247 | Or if you prefer XML: 248 | 249 | :: 250 | 251 | # app/config/config.xml 252 | 253 | 254 | 255 | 259 | 260 | 261 | 262 | 263 | Add authentication routes 264 | ------------------------- 265 | 266 | If you want ready to use login and logout pages, include the built-in 267 | routes: 268 | 269 | :: 270 | 271 | # app/config/routing.yml 272 | fos_user_security: 273 | resource: @FOSUserBundle/Resources/config/routing/security.xml 274 | 275 | fos_user_user: 276 | resource: @FOSUserBundle/Resources/config/routing/user.xml 277 | prefix: /user 278 | 279 | :: 280 | 281 | # app/config/routing.xml 282 | 283 | 284 | 285 | 286 | You now can login at http://app.com/login 287 | 288 | You can also import the group.xml file to use the builtin controllers to 289 | manipulate the groups. 290 | 291 | Command line 292 | ============ 293 | 294 | UserBundle provides command line utilities to help manage your 295 | application users. 296 | 297 | Create user 298 | ----------- 299 | 300 | This command creates a new user:: 301 | 302 | $ php app/console fos:user:create username email password 303 | 304 | If you don't provide the required arguments, a interactive prompt will 305 | ask them to you:: 306 | 307 | $ php app/console fos:user:create 308 | 309 | Promote user as a super administrator 310 | ------------------------------------- 311 | 312 | This command promotes a user as a super administrator:: 313 | 314 | $ php app/console fos:user:promote 315 | 316 | User manager service 317 | ==================== 318 | 319 | UserBundle works with both ORM and ODM. To make it possible, it wraps 320 | all the operation on users in a UserManager. The user manager is a 321 | service of the container. 322 | 323 | If you configure the db_driver to orm, this service is an instance of 324 | ``FOS\UserBundle\Entity\UserManager``. 325 | 326 | If you configure the db_driver to odm, this service is an instance of 327 | ``FOS\UserBundle\Document\UserManager``. 328 | 329 | Both these classes implement ``FOS\UserBundle\Model\UserManagerInterface``. 330 | 331 | Access the user manager service 332 | ------------------------------- 333 | 334 | If you want to manipulate users in a way that will work as well with 335 | ORM and ODM, use the fos_user.user_manager service:: 336 | 337 | $userManager = $container->get('fos_user.user_manager'); 338 | 339 | That's the way UserBundle's internal controllers are built. 340 | 341 | Access the current user class 342 | ----------------------------- 343 | 344 | A new instance of your User class can be created by the user manager:: 345 | 346 | $user = $userManager->createUser(); 347 | 348 | `$user` is now an Entity or a Document, depending on the configuration. 349 | 350 | Configuration example: 351 | ====================== 352 | 353 | All configuration options are listed below:: 354 | 355 | fos_user: 356 | db_driver: mongodb 357 | provider_key: fos_userbundle 358 | class: 359 | model: 360 | user: MyProject\MyBundle\Document\User 361 | group: MyProject\MyBundle\Document\Group 362 | form: 363 | user: ~ 364 | group: ~ 365 | change_password: ~ 366 | reset_password: ~ 367 | controller: 368 | user: ~ 369 | security: ~ 370 | group: ~ 371 | util: 372 | email_canonicalizer: ~ 373 | username_canonicalizer: ~ 374 | service: 375 | util: 376 | mailer: ~ 377 | encoder: 378 | algorithm: ~ 379 | encode_as_base64: ~ 380 | iterations: ~ 381 | form_name: 382 | user: ~ 383 | group: ~ 384 | change_password: ~ 385 | reset_password: ~ 386 | form_validation_groups: 387 | user: ~ # This value is an array of groups 388 | email: 389 | from_email: ~ # { admin@example.com: Sender_name } 390 | confirmation: 391 | enabled: ~ 392 | template: ~ 393 | resetting_password: 394 | template: ~ 395 | token_ttl: ~ 396 | template: 397 | engine: ~ 398 | theme: ~ 399 | 400 | Templating 401 | ---------- 402 | 403 | The template names are not configurable, however Symfony2 makes it possible 404 | to extend a bundle by creating a new Bundle and implementing a getParent() 405 | method inside that new Bundle's definition: 406 | 407 | class MyProjectUserBundle extends Bundle 408 | { 409 | public function getParent() 410 | { 411 | return 'FOSUserBundle'; 412 | } 413 | } 414 | 415 | For example ``src/FOS/UserBundle/Resources/views/User/new.twig`` can be 416 | replaced inside an application by putting a file with alternative content in 417 | ``src/MyProject/FOS/UserBundle/Resources/views/User/new.twig``. 418 | 419 | You can use a different templating engine by configuring it but you will have to 420 | create all the needed templates as only twig templates are provided. 421 | 422 | Validation 423 | ---------- 424 | 425 | The ``Resources/config/validation.xml`` file contains definitions for custom 426 | validator rules for various classes. The rules for the ``User`` class are all in 427 | the ``Registration`` validation group so you can choose not to use them. 428 | 429 | Emails 430 | ------ 431 | 432 | The default mailer relies on Swiftmailer to send the mails of the bundle. If you 433 | want to use another mailer in your project you can change it by defining your 434 | own service implementing ``FOS\UserBundle\Util\MailerInterface`` and setting its 435 | id in the configuration:: 436 | 437 | fos_user: 438 | # ... 439 | service: 440 | util: 441 | mailer: custom_mailer_id 442 | 443 | Canonicalization 444 | ---------------- 445 | 446 | ``Canonicalizer`` services are used to canonicalize the username and the email 447 | fields for database storage. By default, username and email fields are canonicalized 448 | in the same manner using ``mb_convert_case()``. You may configure your own class 449 | for each field provided it implements ``FOS\UserBundle\Util\CanonicalizerInterface``. 450 | 451 | Note:: 452 | If you do not have the mbstring extension installed you will need to 453 | define your own ``canonicalizer``. 454 | -------------------------------------------------------------------------------- /Resources/meta/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 knpLabs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Resources/views/Group/edit.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:Group:edit_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/Group/edit_content.html.twig: -------------------------------------------------------------------------------- 1 | {% form_theme form form.getOption('theme') %} 2 |
3 | {{ form_field(form) }} 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /Resources/views/Group/list.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:Group:list_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/Group/list_content.html.twig: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | -------------------------------------------------------------------------------- /Resources/views/Group/new.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:Group:new_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/Group/new_content.html.twig: -------------------------------------------------------------------------------- 1 | {% form_theme form form.getOption('theme') %} 2 |
3 | {{ form_field(form) }} 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /Resources/views/Group/show.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:Group:show_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/Group/show_content.html.twig: -------------------------------------------------------------------------------- 1 |
2 |

{% trans "Groupname" from 'FOSUserBundle' %}: {{ group.getName() }}

3 |
4 | -------------------------------------------------------------------------------- /Resources/views/Security/login.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% if error %} 5 |
{{ error }}
6 | {% endif %} 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |

21 | {% trans 'Forgotten password' from 'FOSUserBundle' %} 22 |

23 | {% endblock content %} 24 | -------------------------------------------------------------------------------- /Resources/views/User/changePassword.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:changePassword_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/changePassword_content.html.twig: -------------------------------------------------------------------------------- 1 | {% form_theme form form.getOption('theme') %} 2 |
3 | {{ form_field(form) }} 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /Resources/views/User/checkConfirmationEmail.html.twig: -------------------------------------------------------------------------------- 1 | {% set email = user.getEmail() %} 2 | {% trans from 'FOSUserBundle' %} 3 | An email has been sent to %email%. It contains an activation link you must click to activate your account. 4 | {% endtrans %} 5 | -------------------------------------------------------------------------------- /Resources/views/User/checkResettingEmail.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% set email = user.getEmail() %} 5 |

6 | {% trans from 'FOSUserBundle' %} 7 | An email has been sent to %email%. It contains an link you must click to reset your password. 8 | {% endtrans %} 9 |

10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /Resources/views/User/confirmationEmail.txt.twig: -------------------------------------------------------------------------------- 1 | {% set username = user.getUsername() %} 2 | {% trans from 'FOSUserBundle' %} 3 | Welcome %username%! 4 | Hello %username%! 5 | 6 | To finish validating your account - please visit %confirmationUrl% 7 | 8 | Regards, 9 | 10 | the Team. 11 | {% endtrans %} 12 | -------------------------------------------------------------------------------- /Resources/views/User/confirmed.html.twig: -------------------------------------------------------------------------------- 1 | {% set username = user.getUsername() %} 2 | {% trans from 'FOSUserBundle' %} 3 | Congrats %username%, your account is now confirmed. 4 | {% endtrans %} 5 | -------------------------------------------------------------------------------- /Resources/views/User/edit.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:edit_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/edit_content.html.twig: -------------------------------------------------------------------------------- 1 | {% form_theme form form.getOption('theme') %} 2 |
3 | {{ form_field(form) }} 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /Resources/views/User/list.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:list_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/list_content.html.twig: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | -------------------------------------------------------------------------------- /Resources/views/User/new.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:new_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/new_content.html.twig: -------------------------------------------------------------------------------- 1 | {% form_theme form form.getOption('theme') %} 2 |
3 | {{ form_field(form) }} 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /Resources/views/User/passwordAlreadyRequested.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | The password for this user has already been requested within the last 24 hours. 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/requestResetPassword.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:requestResetPassword_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/requestResetPassword_content.html.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |
6 |
7 | 8 |
9 |
-------------------------------------------------------------------------------- /Resources/views/User/resetPassword.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:resetPassword_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/resetPassword_content.html.twig: -------------------------------------------------------------------------------- 1 | {% form_theme form form.getOption('theme') %} 2 |
3 | {{ form_field(form) }} 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /Resources/views/User/resettingPasswordEmail.txt.twig: -------------------------------------------------------------------------------- 1 | {% set username = user.getUsername() %} 2 | {% trans from 'FOSUserBundle' %} 3 | Welcome %username%! 4 | Hello %username%! 5 | 6 | To reset your password - please visit %confirmationUrl% 7 | 8 | Regards, 9 | 10 | the Team. 11 | {% endtrans %} 12 | -------------------------------------------------------------------------------- /Resources/views/User/show.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "FOSUserBundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {% include "FOSUserBundle:User:show_content.html.twig" %} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /Resources/views/User/show_content.html.twig: -------------------------------------------------------------------------------- 1 |
2 |

{% trans "Username" from 'FOSUserBundle' %}: {{ user.getUsername() }}

3 |

{% trans "Email" from 'FOSUserBundle' %}: {{ user.getEmail() }}

4 |
5 | -------------------------------------------------------------------------------- /Resources/views/layout.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 | {% for key, flash in app.session.getFlashes() %} 22 |
23 | {% trans key from 'FOSUserBundle' %} 24 |
25 | {% endfor %} 26 | 27 |
28 | {% block content %} 29 | {% endblock content %} 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /Security/Encoder/EncoderFactory.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * This source file is subject to the MIT license that is bundled 7 | * with this source code in the file LICENSE. 8 | */ 9 | 10 | namespace FOS\UserBundle\Security\Encoder; 11 | 12 | use FOS\UserBundle\Model\UserInterface; 13 | use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; 14 | use Symfony\Component\Security\Core\User\AccountInterface; 15 | 16 | /** 17 | * This factory assumes MessageDigestPasswordEncoder's constructor. 18 | * 19 | * @author Johannes M. Schmitt 20 | * @author Jeremy Mikola 21 | */ 22 | class EncoderFactory implements EncoderFactoryInterface 23 | { 24 | protected $encoders; 25 | protected $encoderClass; 26 | protected $encodeHashAsBase64; 27 | protected $iterations; 28 | protected $genericFactory; 29 | 30 | /** 31 | * Constructor. 32 | * 33 | * @param string $encoderClass Encoder class 34 | * @param Boolean $encodeHashAsBase64 35 | * @param integer $iterations 36 | * @param EncoderFactoryInterface $genericFactory 37 | */ 38 | public function __construct($encoderClass, $encodeHashAsBase64, $iterations, EncoderFactoryInterface $genericFactory) 39 | { 40 | $this->encoders = array(); 41 | $this->encoderClass = $encoderClass; 42 | $this->encodeHashAsBase64 = $encodeHashAsBase64; 43 | $this->iterations = $iterations; 44 | $this->genericFactory = $genericFactory; 45 | } 46 | 47 | /** 48 | * @see Symfony\Component\Security\Core\Encoder\EncoderFactory::getEncoder() 49 | */ 50 | public function getEncoder(AccountInterface $account) 51 | { 52 | if (!$account instanceof UserInterface) { 53 | return $this->genericFactory->getEncoder($account); 54 | } 55 | 56 | if (isset($this->encoders[$algorithm = $account->getAlgorithm()])) { 57 | return $this->encoders[$algorithm]; 58 | } 59 | 60 | return $this->encoders[$algorithm] = $this->createEncoder($algorithm); 61 | } 62 | 63 | /** 64 | * Creates an encoder for the given algorithm. 65 | * 66 | * @param string $algorithm 67 | * @return PasswordEncoderInterface 68 | */ 69 | protected function createEncoder($algorithm) 70 | { 71 | $class = $this->encoderClass; 72 | 73 | return new $class( 74 | $algorithm, 75 | $this->encodeHashAsBase64, 76 | $this->iterations 77 | ); 78 | } 79 | } -------------------------------------------------------------------------------- /Security/InteractiveLoginListener.php: -------------------------------------------------------------------------------- 1 | userManager = $userManager; 18 | } 19 | 20 | public function listenToInteractiveLogin(Event $event) 21 | { 22 | $user = $event->get('token')->getUser(); 23 | 24 | if ($user instanceof User) { 25 | $user->setLastLogin(new DateTime()); 26 | $this->userManager->updateUser($user); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Templating/Helper/SecurityHelper.php: -------------------------------------------------------------------------------- 1 | context->getToken()->getUser(); 22 | } 23 | 24 | /** 25 | * Tells whether the authenticated user is this user 26 | * 27 | * @return bool 28 | **/ 29 | public function isUser(User $user) 30 | { 31 | $authenticatedUser = $this->getUser(); 32 | 33 | return $authenticatedUser instanceof User && $authenticatedUser->isUser($user); 34 | } 35 | 36 | /** 37 | * Tell whether or not a user is logged in 38 | * 39 | * @return bool 40 | **/ 41 | public function isAuthenticated() 42 | { 43 | return null !== $this->context->getToken(); 44 | } 45 | 46 | /** 47 | * Tell whether or not the user is anonymous 48 | * 49 | * @return bool 50 | **/ 51 | public function isAnonymous() 52 | { 53 | return false === $this->vote('IS_AUTHENTICATED_FULLY'); 54 | } 55 | 56 | /** 57 | * Returns the canonical name of this helper. 58 | * 59 | * @return string The canonical name 60 | */ 61 | public function getName() 62 | { 63 | return 'fos_user_security'; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Test/WebTestCase.php: -------------------------------------------------------------------------------- 1 | createKernel(); 19 | $kernel->boot(); 20 | 21 | $application = new Application($kernel); 22 | $application->setAutoExit(false); 23 | 24 | $input = new ArrayInput($params); 25 | $input->setInteractive(false); 26 | 27 | $ouput = new NullOutput(0); 28 | 29 | $application->run($input, $ouput); 30 | } 31 | 32 | protected function getService($name) 33 | { 34 | if (null === $this->kernel) { 35 | $this->kernel = $this->createKernel(); 36 | $this->kernel->boot(); 37 | } 38 | 39 | return $this->kernel->getContainer()->get($name); 40 | } 41 | 42 | protected function removeTestUser() 43 | { 44 | $userManager = $this->getService('fos_user.user_manager'); 45 | if ($user = $userManager->findUserByUsername('test_username')) { 46 | $userManager->deleteUser($user); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/Command/ActivateUserCommandTest.php: -------------------------------------------------------------------------------- 1 | createKernel(); 17 | $command = new ActivateUserCommand(); 18 | $application = new Application($kernel); 19 | $application->setAutoExit(false); 20 | $tester = new ApplicationTester($application); 21 | 22 | $username = 'test_username'; 23 | $password = 'test_password'; 24 | $email = 'test_email@email.org'; 25 | 26 | $userManager = $this->getService('fos_user.user_manager'); 27 | 28 | $user = $userManager->createUser(); 29 | $user->setUsername($username); 30 | $user->setEmail($email); 31 | $user->setPlainPassword($password); 32 | $user->setEnabled(false); 33 | 34 | $userManager->updateUser($user); 35 | 36 | $this->assertFalse($user->isEnabled()); 37 | 38 | $tester->run(array( 39 | 'command' => $command->getFullName(), 40 | 'username' => $username, 41 | ), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); 42 | 43 | $this->getService('doctrine.orm.default_entity_manager')->clear(); 44 | 45 | $userManager = $this->getService('fos_user.user_manager'); 46 | $user = $userManager->findUserByUsername($username); 47 | 48 | $this->assertTrue($user instanceof User); 49 | $this->assertTrue($user->isEnabled()); 50 | 51 | $userManager->updateUser($user); 52 | } 53 | 54 | protected function tearDown() 55 | { 56 | $this->removeTestUser(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Tests/Command/CreateUserCommandTest.php: -------------------------------------------------------------------------------- 1 | createKernel(); 17 | $command = new CreateUserCommand(); 18 | $application = new Application($kernel); 19 | $application->setAutoExit(false); 20 | $tester = new ApplicationTester($application); 21 | $username = 'test_username'; 22 | $password = 'test_password'; 23 | $email = 'test_email@email.org'; 24 | $tester->run(array( 25 | 'command' => $command->getFullName(), 26 | 'username' => $username, 27 | 'password' => $password, 28 | 'email' => $email, 29 | ), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); 30 | 31 | $userManager = $this->getService('fos_user.user_manager'); 32 | $user = $userManager->findUserByUsername($username); 33 | 34 | $this->assertTrue($user instanceof User); 35 | $this->assertEquals($email, $user->getEmail()); 36 | 37 | $userManager->deleteUser($user); 38 | } 39 | 40 | public function testUserCreationWithOptions() 41 | { 42 | $kernel = $this->createKernel(); 43 | $command = new CreateUserCommand(); 44 | $application = new Application($kernel); 45 | $application->setAutoExit(false); 46 | $tester = new ApplicationTester($application); 47 | $username = 'test_username'; 48 | $password = 'test_password'; 49 | $email = 'test_email@email.org'; 50 | $tester->run(array( 51 | 'command' => $command->getFullName(), 52 | 'username' => $username, 53 | 'password' => $password, 54 | 'email' => $email, 55 | '--inactive' => true, 56 | '--super-admin' => true 57 | ), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); 58 | 59 | $userManager = $this->getService('fos_user.user_manager'); 60 | $user = $userManager->findUserByUsername($username); 61 | 62 | $this->assertTrue($user instanceof User); 63 | $this->assertEquals($email, $user->getEmail()); 64 | $this->assertFalse($user->isEnabled()); 65 | $this->assertTrue($user->hasRole('ROLE_SUPERADMIN')); 66 | 67 | $userManager->deleteUser($user); 68 | } 69 | 70 | protected function tearDown() 71 | { 72 | $this->removeTestUser(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Tests/Command/DeactivateUserCommandTest.php: -------------------------------------------------------------------------------- 1 | createKernel(); 17 | $command = new DeactivateUserCommand(); 18 | $application = new Application($kernel); 19 | $application->setAutoExit(false); 20 | $tester = new ApplicationTester($application); 21 | 22 | $username = 'test_username'; 23 | $password = 'test_password'; 24 | $email = 'test_email@email.org'; 25 | 26 | $userManager = $this->getService('fos_user.user_manager'); 27 | 28 | $user = $userManager->createUser(); 29 | $user->setUsername($username); 30 | $user->setEmail($email); 31 | $user->setPlainPassword($password); 32 | $user->setEnabled(true); 33 | 34 | $userManager->updateUser($user); 35 | 36 | $this->assertTrue($user->isEnabled()); 37 | 38 | $tester->run(array( 39 | 'command' => $command->getFullName(), 40 | 'username' => $username, 41 | ), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); 42 | 43 | $this->getService('doctrine.orm.default_entity_manager')->clear(); 44 | 45 | $userManager = $this->getService('fos_user.user_manager'); 46 | $user = $userManager->findUserByUsername($username); 47 | 48 | $this->assertTrue($user instanceof User); 49 | $this->assertFalse($user->isEnabled()); 50 | 51 | $userManager->deleteUser($user); 52 | } 53 | 54 | protected function tearDown() 55 | { 56 | $this->removeTestUser(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Tests/Command/DemoteSuperUserCommandTest.php: -------------------------------------------------------------------------------- 1 | createKernel(); 17 | $command = new DemoteSuperAdminCommand(); 18 | $application = new Application($kernel); 19 | $application->setAutoExit(false); 20 | $tester = new ApplicationTester($application); 21 | 22 | $username = 'test_username'; 23 | $password = 'test_password'; 24 | $email = 'test_email@email.org'; 25 | 26 | $userManager = $this->getService('fos_user.user_manager'); 27 | 28 | $user = $userManager->createUser(); 29 | $user->setUsername($username); 30 | $user->setEmail($email); 31 | $user->setPlainPassword($password); 32 | $user->addRole('ROLE_SUPERADMIN'); 33 | 34 | $userManager->updateUser($user); 35 | 36 | $this->assertTrue($user->hasRole('ROLE_SUPERADMIN')); 37 | 38 | $tester->run(array( 39 | 'command' => $command->getFullName(), 40 | 'username' => $username, 41 | ), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); 42 | 43 | $this->getService('doctrine.orm.default_entity_manager')->clear(); 44 | 45 | $userManager = $this->getService('fos_user.user_manager'); 46 | $user = $userManager->findUserByUsername($username); 47 | 48 | $this->assertTrue($user instanceof User); 49 | $this->assertFalse($user->hasRole('ROLE_SUPERADMIN')); 50 | 51 | $userManager->deleteUser($user); 52 | } 53 | 54 | protected function tearDown() 55 | { 56 | $this->removeTestUser(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Tests/Command/PromoteSuperUserCommandTest.php: -------------------------------------------------------------------------------- 1 | createKernel(); 17 | $command = new PromoteSuperAdminCommand(); 18 | $application = new Application($kernel); 19 | $application->setAutoExit(false); 20 | $tester = new ApplicationTester($application); 21 | $username = 'test_username'; 22 | $password = 'test_password'; 23 | $email = 'test_email@email.org'; 24 | $userManager = $kernel->getContainer()->get('fos_user.user_manager'); 25 | $user = $userManager->createUser(); 26 | $user->setUsername($username); 27 | $user->setEmail($email); 28 | $user->setPlainPassword($password); 29 | $userManager->updateUser($user); 30 | $this->assertFalse($user->hasRole('ROLE_SUPERADMIN')); 31 | $tester->run(array( 32 | 'command' => $command->getFullName(), 33 | 'username' => $username, 34 | ), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); 35 | 36 | $userManager = $this->getService('fos_user.user_manager'); 37 | $user = $userManager->findUserByUsername($username); 38 | 39 | $this->assertTrue($user instanceof User); 40 | $this->assertTrue($user->hasRole('ROLE_SUPERADMIN')); 41 | 42 | $userManager->deleteUser($user); 43 | } 44 | 45 | protected function tearDown() 46 | { 47 | $this->removeTestUser(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/Document/DocumentUserManagerTest.php: -------------------------------------------------------------------------------- 1 | userManager->expects($this->once()) 12 | ->method('findUserBy') 13 | ->with($this->equalTo(array('usernameCanonical' => 'jack'))); 14 | 15 | $this->userManager->findUserByUsername('jack'); 16 | } 17 | 18 | public function testFindUserByUsernameLowercasesTheUsername() 19 | { 20 | $this->userManager->expects($this->once()) 21 | ->method('findUserBy') 22 | ->with($this->equalTo(array('usernameCanonical' => 'jack'))); 23 | 24 | $this->userManager->findUserByUsername('JaCk'); 25 | } 26 | 27 | public function testFindUserByEmail() 28 | { 29 | $this->userManager->expects($this->once()) 30 | ->method('findUserBy') 31 | ->with($this->equalTo(array('email' => 'jack@email.org'))); 32 | 33 | $this->userManager->findUserByEmail('jack@email.org'); 34 | } 35 | 36 | public function testFindUserByEmailLowercasesTheEmail() 37 | { 38 | $this->userManager->expects($this->once()) 39 | ->method('findUserBy') 40 | ->with($this->equalTo(array('email' => 'jack@email.org'))); 41 | 42 | $this->userManager->findUserByEmail('JaCk@EmAiL.oRg'); 43 | } 44 | 45 | public function testFindUserByUsernameOrEmailWithUsername() 46 | { 47 | $this->userManager->expects($this->once()) 48 | ->method('findUserBy') 49 | ->with($this->equalTo(array('usernameCanonical' => 'jack'))); 50 | 51 | $this->userManager->findUserByUsernameOrEmail('JaCk'); 52 | } 53 | 54 | public function testFindUserByUsernameOrEmailWithEmail() 55 | { 56 | $this->userManager->expects($this->once()) 57 | ->method('findUserBy') 58 | ->with($this->equalTo(array('email' => 'jack@email.org'))); 59 | 60 | $this->userManager->findUserByUsernameOrEmail('JaCk@EmAiL.oRg'); 61 | } 62 | 63 | public function testLoadUserByUsernameWithExistingUser() 64 | { 65 | $userMock = $this->getMock('FOS\UserBundle\Document\User', array(), array('sha1')); 66 | 67 | $this->userManager->expects($this->once()) 68 | ->method('findUserBy') 69 | ->with($this->equalTo(array('usernameCanonical' => 'jack'))) 70 | ->will($this->returnValue($userMock)); 71 | 72 | $this->userManager->loadUserByUsername('jack'); 73 | } 74 | 75 | /** 76 | * @expectedException Symfony\Component\Security\Core\Exception\UsernameNotFoundException 77 | */ 78 | public function testLoadUserByUsernameWithMissingUser() 79 | { 80 | $this->userManager->expects($this->once()) 81 | ->method('findUserBy') 82 | ->with($this->equalTo(array('usernameCanonical' => 'jack'))) 83 | ->will($this->returnValue(null)); 84 | 85 | $this->userManager->loadUserByUsername('jack'); 86 | } 87 | 88 | protected function setUp() 89 | { 90 | if (!class_exists('\Doctrine\ODM\MongoDB\DocumentManager')) { 91 | $this->markTestSkipped('No ODM installed'); 92 | } 93 | 94 | $this->userManager = $this->getManagerMock(); 95 | } 96 | 97 | protected function tearDown() 98 | { 99 | unset($this->userManager); 100 | } 101 | 102 | protected function getManagerMock() 103 | { 104 | $methods = array('findUserBy'); 105 | $userManager = $this->getMock('FOS\UserBundle\Document\UserManager', $methods, array(), '', false); 106 | 107 | return $userManager; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Tests/Model/UserManagerTest.php: -------------------------------------------------------------------------------- 1 | encoderFactory = $this->getMockEncoderFactory(); 16 | $this->algorithm = 'sha512'; 17 | $this->usernameCanonicalizer = $this->getMockCanonicalizer(); 18 | $this->emailCanonicalizer = $this->getMockCanonicalizer(); 19 | 20 | $this->manager = $this->getUserManager(array( 21 | $this->encoderFactory, 22 | $this->algorithm, 23 | $this->usernameCanonicalizer, 24 | $this->emailCanonicalizer, 25 | )); 26 | } 27 | 28 | public function testUpdateCanonicalFields() 29 | { 30 | $user = $this->getUser(); 31 | $user->setUsername('Username'); 32 | $user->setEmail('User@Example.com'); 33 | 34 | $this->usernameCanonicalizer->expects($this->once()) 35 | ->method('canonicalize') 36 | ->with('Username') 37 | ->will($this->returnCallback('strtolower')); 38 | 39 | $this->emailCanonicalizer->expects($this->once()) 40 | ->method('canonicalize') 41 | ->with('User@Example.com') 42 | ->will($this->returnCallback('strtolower')); 43 | 44 | $this->manager->updateCanonicalFields($user); 45 | $this->assertEquals('username', $user->getUsernameCanonical()); 46 | $this->assertEquals('user@example.com', $user->getEmailCanonical()); 47 | } 48 | 49 | public function testUpdatePassword() 50 | { 51 | $encoder = $this->getMockPasswordEncoder(); 52 | $user = $this->getUser(); 53 | $user->setPlainPassword('password'); 54 | 55 | $this->encoderFactory->expects($this->once()) 56 | ->method('getEncoder') 57 | ->will($this->returnValue($encoder)); 58 | 59 | $encoder->expects($this->once()) 60 | ->method('encodePassword') 61 | ->with('password', $user->getSalt()) 62 | ->will($this->returnValue('encodedPassword')); 63 | 64 | $this->manager->updatePassword($user); 65 | $this->assertEquals($this->algorithm, $user->getAlgorithm(), '->updatePassword() sets algorithm'); 66 | $this->assertEquals('encodedPassword', $user->getPassword(), '->updatePassword() sets encoded password'); 67 | $this->assertNull($user->getPlainPassword(), '->updatePassword() erases credentials'); 68 | } 69 | 70 | private function getMockCanonicalizer() 71 | { 72 | return $this->getMock('FOS\UserBundle\Util\CanonicalizerInterface'); 73 | } 74 | 75 | private function getMockEncoderFactory() 76 | { 77 | return $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface'); 78 | } 79 | 80 | private function getMockPasswordEncoder() 81 | { 82 | return $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface'); 83 | } 84 | 85 | private function getUser() 86 | { 87 | return $this->getMockBuilder('FOS\UserBundle\Model\User') 88 | ->getMockForAbstractClass(); 89 | } 90 | 91 | private function getUserManager(array $args) 92 | { 93 | return $this->getMockBuilder('FOS\UserBundle\Model\UserManager') 94 | ->setConstructorArgs($args) 95 | ->getMockForAbstractClass(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Tests/Model/UserTest.php: -------------------------------------------------------------------------------- 1 | getUser(); 10 | $this->assertNull($user->getUsername()); 11 | 12 | $user->setUsername('tony'); 13 | $this->assertEquals('tony', $user->getUsername()); 14 | } 15 | 16 | public function testEmail() 17 | { 18 | $user = $this->getUser(); 19 | $this->assertNull($user->getEmail()); 20 | 21 | $user->setEmail('tony@mail.org'); 22 | $this->assertEquals('tony@mail.org', $user->getEmail()); 23 | } 24 | 25 | /** 26 | * @covers FOS\UserBundle\Model\User::getPasswordRequestedAt 27 | * @covers FOS\UserBundle\Model\User::setPasswordRequestedAt 28 | * @covers FOS\UserBundle\Model\User::isPasswordRequestNonExpired 29 | */ 30 | public function testIsPasswordRequestNonExpired() 31 | { 32 | $user = $this->getUser(); 33 | $passwordRequestedAt = new \DateTime('-10 seconds'); 34 | 35 | $user->setPasswordRequestedAt($passwordRequestedAt); 36 | 37 | $this->assertSame($passwordRequestedAt, $user->getPasswordRequestedAt()); 38 | $this->assertTrue($user->isPasswordRequestNonExpired(15)); 39 | $this->assertFalse($user->isPasswordRequestNonExpired(5)); 40 | } 41 | 42 | protected function getUser() 43 | { 44 | return $this->getMockForAbstractClass('FOS\UserBundle\Model\User'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/Security/Encoder/EncoderFactoryTest.php: -------------------------------------------------------------------------------- 1 | getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface') 21 | ); 22 | 23 | $userAccount = $this->getMock('FOS\UserBundle\Model\UserInterface'); 24 | 25 | $userAccount->expects($this->once()) 26 | ->method('getAlgorithm') 27 | ->will($this->returnValue('sha512')); 28 | 29 | $encoder = $factory->getEncoder($userAccount); 30 | 31 | $expectedEncoder = new MessageDigestPasswordEncoder('sha512', false, 1); 32 | 33 | $this->assertEquals($expectedEncoder->encodePassword('foo', 'bar'), $encoder->encodePassword('foo', 'bar')); 34 | } 35 | 36 | public function testGetEncoderWithGenericAccount() 37 | { 38 | $genericFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface'); 39 | $encoder = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface'); 40 | 41 | $genericFactory 42 | ->expects($this->once()) 43 | ->method('getEncoder') 44 | ->will($this->returnValue($encoder)) 45 | ; 46 | 47 | $factory = new EncoderFactory(null , false, 1, $genericFactory); 48 | 49 | $this->assertSame($encoder, $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\AccountInterface'))); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Tests/Validation/UserValidationTest.php: -------------------------------------------------------------------------------- 1 | getService('fos_user.user_manager')->createUser(); 12 | $violations = $this->getService('validator')->validate($user, 'Registration'); 13 | $this->assertTrue($this->hasViolationForPropertyPath($violations, 'username')); 14 | } 15 | 16 | public function testGoodUsernameValid() 17 | { 18 | $user = $this->getService('fos_user.user_manager')->createUser(); 19 | $user->setUsername(uniqid()); 20 | $violations = $this->getService('validator')->validate($user, 'Registration'); 21 | $this->assertFalse($this->hasViolationForPropertyPath($violations, 'username')); 22 | } 23 | 24 | public function testDuplicatedUsernameFail() 25 | { 26 | $username = uniqid(); 27 | $userManager = $this->getService('fos_user.user_manager'); 28 | $user1 = $userManager->createUser(); 29 | $user1->setUsername($username); 30 | $user1->setEmail(uniqid().'@mail.org'); 31 | $user1->setPlainPassword(uniqid()); 32 | $violations = $this->getService('validator')->validate($user1, 'Registration'); 33 | $this->assertFalse($this->hasViolationForPropertyPath($violations, 'username')); 34 | $userManager->updateUser($user1); 35 | 36 | $user2 = $userManager->createUser(); 37 | $user2->setUsername($username); 38 | $user1->setEmail(uniqid().'@mail.org'); 39 | $user1->setPlainPassword(uniqid()); 40 | $violations = $this->getService('validator')->validate($user2, 'Registration'); 41 | $this->assertTrue($this->hasViolationForPropertyPath($violations, 'username')); 42 | $userManager->deleteUser($user1); 43 | } 44 | 45 | public function testDuplicatedEmailFail() 46 | { 47 | $email = uniqid().'@email.org'; 48 | $userManager = $this->getService('fos_user.user_manager'); 49 | $user1 = $userManager->createUser(); 50 | $user1->setUsername(uniqid()); 51 | $user1->setPlainPassword(uniqid()); 52 | $user1->setEmail($email); 53 | $violations = $this->getService('validator')->validate($user1, 'Registration'); 54 | $this->assertFalse($this->hasViolationForPropertyPath($violations, 'email')); 55 | $userManager->updateUser($user1); 56 | 57 | $user2 = $userManager->createUser(); 58 | $user2->setUsername(uniqid()); 59 | $user2->setPlainPassword(uniqid()); 60 | $user2->setEmail($email); 61 | $violations = $this->getService('validator')->validate($user2, 'Registration'); 62 | $this->assertTrue($this->hasViolationForPropertyPath($violations, 'email')); 63 | $userManager->deleteUser($user1); 64 | } 65 | 66 | protected function hasViolationForPropertyPath($violations, $propertyPath) 67 | { 68 | if (!is_object($violations)) { 69 | return false; 70 | } 71 | 72 | foreach ($violations as $violation) { 73 | if ($violation->getPropertyPath() == $propertyPath) { 74 | return true; 75 | } 76 | } 77 | 78 | return false; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | registerNamespace('Symfony', $_SERVER['SYMFONY']); 9 | $loader->register(); 10 | 11 | spl_autoload_register(function($class) 12 | { 13 | if (0 === strpos($class, 'FOS\\UserBundle\\')) { 14 | $path = implode('/', array_slice(explode('\\', $class), 2)).'.php'; 15 | require_once __DIR__.'/../'.$path; 16 | return true; 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /Twig/UserExtension.php: -------------------------------------------------------------------------------- 1 | securityContext = $securityContext; 16 | } 17 | 18 | /** 19 | * Returns a list of global functions to add to the existing list. 20 | * 21 | * @return array An array of global functions 22 | */ 23 | public function getFunctions() 24 | { 25 | return array( 26 | 'fos_user_getUser' => new Twig_Function_Method($this, 'getUser'), 27 | 'fos_user_isUser' => new Twig_Function_Method($this, 'isUser'), 28 | 'fos_user_isAuthenticated' => new Twig_Function_Method($this, 'isAuthenticated'), 29 | 'fos_user_isAnonymous' => new Twig_Function_Method($this, 'isAnonymous'), 30 | ); 31 | } 32 | 33 | /** 34 | * Returns the authenticated user, if any 35 | * 36 | * @return FOS\UserBundle\Model\User 37 | */ 38 | public function getUser() 39 | { 40 | return $this->securityContext->getToken()->getUser(); 41 | } 42 | 43 | /** 44 | * Tells whether the authenticated user is this user 45 | * 46 | * @return bool 47 | */ 48 | public function isUser(User $user) 49 | { 50 | $authenticatedUser = $this->getUser(); 51 | 52 | return $authenticatedUser instanceof User && $authenticatedUser->isUser($user); 53 | } 54 | 55 | /** 56 | * Tell whether or not a user is logged in 57 | * 58 | * @return boolean 59 | */ 60 | public function isAuthenticated() 61 | { 62 | return null !== $this->securityContext->getToken(); 63 | } 64 | 65 | /** 66 | * Tell whether or not the user is anonymous 67 | * 68 | * @return boolean 69 | */ 70 | public function isAnonymous() 71 | { 72 | return false === $this->securityContext->vote('IS_AUTHENTICATED_FULLY'); 73 | } 74 | 75 | /** 76 | * Returns the name of the extension. 77 | * 78 | * @return string The extension name 79 | */ 80 | public function getName() 81 | { 82 | return 'fos_user'; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Util/Canonicalizer.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * This source file is subject to the MIT license that is bundled 7 | * with this source code in the file LICENSE. 8 | */ 9 | 10 | namespace FOS\UserBundle\Util; 11 | 12 | use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; 13 | use Symfony\Component\Routing\RouterInterface; 14 | use FOS\UserBundle\Model\UserInterface; 15 | 16 | class Mailer implements MailerInterface 17 | { 18 | protected $mailer; 19 | protected $router; 20 | protected $templating; 21 | protected $parameters; 22 | 23 | public function __construct($mailer, RouterInterface $router, EngineInterface $templating, array $parameters) 24 | { 25 | $this->mailer = $mailer; 26 | $this->router = $router; 27 | $this->templating = $templating; 28 | $this->parameters = $parameters; 29 | } 30 | 31 | public function sendConfirmationEmailMessage(UserInterface $user, $engine) 32 | { 33 | $template = $this->parameters['confirmation.template']; 34 | $url = $this->router->generate('fos_user_user_confirm', array('token' => $user->getConfirmationToken()), true); 35 | $rendered = $this->templating->render($template.'.txt.'.$engine, array( 36 | 'user' => $user, 37 | 'confirmationUrl' => $url 38 | )); 39 | $this->sendEmailMessage($rendered, $this->getSenderEmail('confirmation'), $user->getEmail()); 40 | } 41 | 42 | public function sendResettingEmailMessage(UserInterface $user, $engine) 43 | { 44 | $template = $this->parameters['resetting_password.template']; 45 | $url = $this->router->generate('fos_user_user_reset_password', array('token' => $user->getConfirmationToken()), true); 46 | $rendered = $this->templating->render($template.'.txt.'.$engine, array( 47 | 'user' => $user, 48 | 'confirmationUrl' => $url 49 | )); 50 | $this->sendEmailMessage($rendered, $this->getSenderEmail('resetting_password'), $user->getEmail()); 51 | } 52 | 53 | protected function sendEmailMessage($renderedTemplate, $fromEmail, $toEmail) 54 | { 55 | // Render the email, use the first line as the subject, and the rest as the body 56 | $renderedLines = explode("\n", trim($renderedTemplate)); 57 | $subject = $renderedLines[0]; 58 | $body = implode("\n", array_slice($renderedLines, 1)); 59 | 60 | $message = \Swift_Message::newInstance() 61 | ->setSubject($subject) 62 | ->setFrom($fromEmail) 63 | ->setTo($toEmail) 64 | ->setBody($body); 65 | 66 | $this->mailer->send($message); 67 | } 68 | 69 | protected function getSenderEmail($type) 70 | { 71 | return $this->parameters['from_email'][$type]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Util/MailerInterface.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * This source file is subject to the MIT license that is bundled 7 | * with this source code in the file LICENSE. 8 | */ 9 | 10 | namespace FOS\UserBundle\Util; 11 | 12 | use FOS\UserBundle\Model\UserInterface; 13 | 14 | interface MailerInterface 15 | { 16 | function sendConfirmationEmailMessage(UserInterface $user, $engine); 17 | 18 | function sendResettingEmailMessage(UserInterface $user, $engine); 19 | } 20 | -------------------------------------------------------------------------------- /Validator/Password.php: -------------------------------------------------------------------------------- 1 | encoderFactory = $factory; 16 | } 17 | 18 | public function isValid($object, Constraint $constraint) 19 | { 20 | if (!is_object($object)) { 21 | throw new \RuntimeException('This is a class constraint.'); 22 | } 23 | 24 | $raw = $object->{$constraint->passwordProperty}; 25 | $user = null === $constraint->userProperty ? $object : $object->{$constraint->userProperty}; 26 | $encoder = $this->encoderFactory->getEncoder($user); 27 | 28 | if (!$encoder->isPasswordValid($user->getPassword(), $raw, $user->getSalt())) { 29 | $this->setMessage($constraint->message); 30 | return false; 31 | } 32 | 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Validator/Unique.php: -------------------------------------------------------------------------------- 1 | userManager = $userManager; 29 | } 30 | 31 | /** 32 | * Sets the user manager 33 | * 34 | * @param UserManager $userManager 35 | */ 36 | public function setUserManager(UserManager $userManager) 37 | { 38 | $this->userManager = $userManager; 39 | } 40 | 41 | /** 42 | * Gets the user manager 43 | * 44 | * @return UserManager 45 | */ 46 | public function getUserManager() 47 | { 48 | return $this->userManager; 49 | } 50 | 51 | /** 52 | * Indicates whether the constraint is valid 53 | * 54 | * @param Entity $value 55 | * @param Constraint $constraint 56 | */ 57 | public function isValid($value, Constraint $constraint) 58 | { 59 | if (!$this->getUserManager()->validateUnique($value, $constraint)) { 60 | $this->setMessage($constraint->message, array( 61 | 'property' => $constraint->property 62 | )); 63 | return false; 64 | } 65 | 66 | return true; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | ./Tests 13 | 14 | 15 | 16 | 17 | 18 | ./ 19 | 20 | ./Resources 21 | ./Tests 22 | 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------