1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Security\Core\User;
13
14use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
15use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
16
17/**
18 * InMemoryUserProvider is a simple non persistent user provider.
19 *
20 * Useful for testing, demonstration, prototyping, and for simple needs
21 * (a backend with a unique admin for instance)
22 *
23 * @author Fabien Potencier <fabien@symfony.com>
24 */
25class InMemoryUserProvider implements UserProviderInterface
26{
27    private $users;
28
29    /**
30     * The user array is a hash where the keys are usernames and the values are
31     * an array of attributes: 'password', 'enabled', and 'roles'.
32     *
33     * @param array $users An array of users
34     */
35    public function __construct(array $users = [])
36    {
37        foreach ($users as $username => $attributes) {
38            $password = isset($attributes['password']) ? $attributes['password'] : null;
39            $enabled = isset($attributes['enabled']) ? $attributes['enabled'] : true;
40            $roles = isset($attributes['roles']) ? $attributes['roles'] : [];
41            $user = new User($username, $password, $roles, $enabled, true, true, true);
42
43            $this->createUser($user);
44        }
45    }
46
47    /**
48     * Adds a new User to the provider.
49     *
50     * @throws \LogicException
51     */
52    public function createUser(UserInterface $user)
53    {
54        if (isset($this->users[strtolower($user->getUsername())])) {
55            throw new \LogicException('Another user with the same username already exists.');
56        }
57
58        $this->users[strtolower($user->getUsername())] = $user;
59    }
60
61    /**
62     * {@inheritdoc}
63     */
64    public function loadUserByUsername($username)
65    {
66        $user = $this->getUser($username);
67
68        return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(), $user->isCredentialsNonExpired(), $user->isAccountNonLocked());
69    }
70
71    /**
72     * {@inheritdoc}
73     */
74    public function refreshUser(UserInterface $user)
75    {
76        if (!$user instanceof User) {
77            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user)));
78        }
79
80        $storedUser = $this->getUser($user->getUsername());
81
82        return new User($storedUser->getUsername(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled(), $storedUser->isAccountNonExpired(), $storedUser->isCredentialsNonExpired() && $storedUser->getPassword() === $user->getPassword(), $storedUser->isAccountNonLocked());
83    }
84
85    /**
86     * {@inheritdoc}
87     */
88    public function supportsClass($class)
89    {
90        return 'Symfony\Component\Security\Core\User\User' === $class;
91    }
92
93    /**
94     * Returns the user by given username.
95     *
96     * @param string $username The username
97     *
98     * @return User
99     *
100     * @throws UsernameNotFoundException if user whose given username does not exist
101     */
102    private function getUser($username)
103    {
104        if (!isset($this->users[strtolower($username)])) {
105            $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
106            $ex->setUsername($username);
107
108            throw $ex;
109        }
110
111        return $this->users[strtolower($username)];
112    }
113}
114