Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
AdminAccount.php
Go to the documentation of this file.
1 <?php
7 namespace Magento\Setup\Model;
8 
14 
16 {
20  const KEY_USER = 'admin-user';
21  const KEY_PASSWORD = 'admin-password';
22  const KEY_EMAIL = 'admin-email';
23  const KEY_FIRST_NAME = 'admin-firstname';
24  const KEY_LAST_NAME = 'admin-lastname';
25  const KEY_PREFIX = 'db-prefix';
33  private $connection;
34 
40  private $data;
41 
45  private $encryptor;
46 
54  public function __construct(
55  AdapterInterface $connection,
56  EncryptorInterface $encryptor,
57  array $data
58  ) {
59  $this->connection = $connection;
60  $this->encryptor = $encryptor;
61  $this->data = $data;
62  }
63 
69  protected function generatePassword()
70  {
71  return $this->encryptor->getHash($this->data[self::KEY_PASSWORD], true);
72  }
73 
81  public function save()
82  {
83  $adminId = $this->saveAdminUser();
84  $this->saveAdminUserRole($adminId);
85  }
86 
95  private function saveAdminUser()
96  {
97  $passwordHash = $this->generatePassword();
98  $adminData = [
99  'firstname' => $this->data[self::KEY_FIRST_NAME],
100  'lastname' => $this->data[self::KEY_LAST_NAME],
101  'password' => $passwordHash,
102  'is_active' => 1,
103  ];
104  $result = $this->connection->fetchRow(
105  'SELECT user_id, username, email FROM ' . $this->getTableName('admin_user') . ' ' .
106  'WHERE username = :username OR email = :email',
107  ['username' => $this->data[self::KEY_USER], 'email' => $this->data[self::KEY_EMAIL]],
108  null
109  );
110 
111  if (!empty($result)) {
112  // User exists, update
113  $this->validateUserMatches();
114  $adminId = $result['user_id'];
115  $adminData['modified'] = date('Y-m-d H:i:s');
116 
117  $this->connection->update(
118  $this->getTableName('admin_user'),
119  $adminData,
120  $this->connection->quoteInto('username = ?', $this->data[self::KEY_USER])
121  );
122  } else {
123  // User does not exist, create it
124  $adminData['username'] = $this->data[self::KEY_USER];
125  $adminData['email'] = $this->data[self::KEY_EMAIL];
126  $this->connection->insert(
127  $this->getTableName('admin_user'),
128  $adminData
129  );
130  $adminId = $this->connection->lastInsertId();
131  }
132  $this->trackPassword($adminId, $passwordHash);
133 
134  return $adminId;
135  }
136 
144  private function trackPassword($adminId, $passwordHash)
145  {
146  $this->connection->insert(
147  $this->getTableName('admin_passwords'),
148  [
149  'user_id' => $adminId,
150  'password_hash' => $passwordHash,
151  'last_updated' => time()
152  ]
153  );
154  }
155 
164  public function validateUserMatches()
165  {
166  if (empty($this->data[self::KEY_PASSWORD])) {
167  throw new \Exception(
168  '"Password" is required. Enter and try again.'
169  );
170  }
171 
172  if (strcasecmp($this->data[self::KEY_PASSWORD], $this->data[self::KEY_USER]) == 0) {
173  throw new \Exception(
174  'Password cannot be the same as the user name.'
175  );
176  }
177 
178  try {
179  $result = $this->connection->fetchRow(
180  "SELECT user_id, username, email FROM {$this->getTableName('admin_user')} "
181  . "WHERE username = :username OR email = :email",
182  ['username' => $this->data[self::KEY_USER], 'email' => $this->data[self::KEY_EMAIL]]
183  );
184  } catch (\Exception $e) {
185  return; // New installation, no need to validate existing users.
186  }
187 
188  $email = $result['email'];
189  $username = $result['username'];
190 
191  if ((strcasecmp($email, $this->data[self::KEY_EMAIL]) == 0) &&
192  (strcasecmp($username, $this->data[self::KEY_USER]) != 0)) {
193  // email matched but username did not
194  throw new \Exception(
195  'An existing user has the given email but different username. '
196  . 'Username and email both need to match an existing user or both be new.'
197  );
198  }
199  if ((strcasecmp($username, $this->data[self::KEY_USER]) == 0) &&
200  (strcasecmp($email, $this->data[self::KEY_EMAIL]) != 0)) {
201  // username matched but email did not
202  throw new \Exception(
203  'An existing user has the given username but different email. '
204  . 'Username and email both need to match an existing user or both be new.'
205  );
206  }
207  }
208 
217  private function saveAdminUserRole($adminId)
218  {
219  $result = $this->connection->fetchRow(
220  'SELECT * FROM ' . $this->getTableName('authorization_role') . ' ' .
221  'WHERE user_id = :user_id AND user_type = :user_type',
222  ['user_id' => $adminId, 'user_type' => UserContextInterface::USER_TYPE_ADMIN]
223  );
224  if (empty($result)) {
225  // No user role exists for this user id, create it
226  $adminRoleData = [
227  'parent_id' => $this->retrieveAdministratorsRoleId(),
228  'tree_level' => 2,
229  'role_type' => User::ROLE_TYPE,
230  'user_id' => $adminId,
232  'role_name' => $this->data[self::KEY_USER],
233  ];
234  $this->connection->insert($this->getTableName('authorization_role'), $adminRoleData);
235  }
236  }
237 
244  private function retrieveAdministratorsRoleId()
245  {
246  // Get Administrators role id to use as parent_id
247  $administratorsRoleData = [
248  'parent_id' => 0,
249  'tree_level' => 1,
250  'role_type' => Group::ROLE_TYPE,
251  'user_id' => 0,
253  'role_name' => 'Administrators',
254  ];
255  $result = $this->connection->fetchRow(
256  'SELECT * FROM ' . $this->getTableName('authorization_role') . ' ' .
257  'WHERE parent_id = :parent_id AND tree_level = :tree_level AND role_type = :role_type AND ' .
258  'user_id = :user_id AND user_type = :user_type AND role_name = :role_name',
259  $administratorsRoleData
260  );
261  if (empty($result)) {
262  throw new \Exception('No Administrators role was found, data fixture needs to be run');
263  } else {
264  // Found at least one, use first
265  return $result['role_id'];
266  }
267  }
268 
275  private function getTableName($table)
276  {
277  if (!empty($this->data[self::KEY_PREFIX])) {
278  return $this->connection->getTableName($this->data[self::KEY_PREFIX] . $table);
279  }
280 
281  return $this->connection->getTableName($table);
282  }
283 }
__construct(AdapterInterface $connection, EncryptorInterface $encryptor, array $data)
$email
Definition: details.phtml:13
$connection
Definition: bulk.php:13
$table
Definition: trigger.php:14