File: /var/www/vhost/disk-apps/magento.bikenow.co/setup/src/Magento/Setup/Model/AdminAccount.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Setup\Model;
use Magento\Authorization\Model\Acl\Role\Group;
use Magento\Authorization\Model\Acl\Role\User;
use Magento\Authorization\Model\UserContextInterface;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
class AdminAccount
{
/**#@+
* Data keys
*/
const KEY_USER = 'admin-user';
const KEY_PASSWORD = 'admin-password';
const KEY_EMAIL = 'admin-email';
const KEY_FIRST_NAME = 'admin-firstname';
const KEY_LAST_NAME = 'admin-lastname';
const KEY_PREFIX = 'db-prefix';
/**#@- */
/**
* Db connection
*
* @var AdapterInterface
*/
private $connection;
/**
* Configurations
*
* @var []
*/
private $data;
/**
* @var EncryptorInterface
*/
private $encryptor;
/**
* Default Constructor
*
* @param AdapterInterface $connection
* @param EncryptorInterface $encryptor
* @param array $data
*/
public function __construct(
AdapterInterface $connection,
EncryptorInterface $encryptor,
array $data
) {
$this->connection = $connection;
$this->encryptor = $encryptor;
$this->data = $data;
}
/**
* Generate password string
*
* @return string
*/
protected function generatePassword()
{
return $this->encryptor->getHash($this->data[self::KEY_PASSWORD], true);
}
/**
* Save administrator account and user role to DB.
*
* If the administrator account exists, update it.
*
* @return void
*/
public function save()
{
$adminId = $this->saveAdminUser();
$this->saveAdminUserRole($adminId);
}
/**
* Uses the information in data[] to create the admin user.
*
* If the username already exists, it will update the record with information from data[]
* and set the is_active flag.
*
* @return int The admin user id
*/
private function saveAdminUser()
{
$passwordHash = $this->generatePassword();
$adminData = [
'firstname' => $this->data[self::KEY_FIRST_NAME],
'lastname' => $this->data[self::KEY_LAST_NAME],
'password' => $passwordHash,
'is_active' => 1,
];
$result = $this->connection->fetchRow(
'SELECT user_id, username, email FROM ' . $this->getTableName('admin_user') . ' ' .
'WHERE username = :username OR email = :email',
['username' => $this->data[self::KEY_USER], 'email' => $this->data[self::KEY_EMAIL]],
null
);
if (!empty($result)) {
// User exists, update
$this->validateUserMatches();
$adminId = $result['user_id'];
$adminData['modified'] = date('Y-m-d H:i:s');
$this->connection->update(
$this->getTableName('admin_user'),
$adminData,
$this->connection->quoteInto('username = ?', $this->data[self::KEY_USER])
);
} else {
// User does not exist, create it
$adminData['username'] = $this->data[self::KEY_USER];
$adminData['email'] = $this->data[self::KEY_EMAIL];
$this->connection->insert(
$this->getTableName('admin_user'),
$adminData
);
$adminId = $this->connection->lastInsertId();
}
$this->trackPassword($adminId, $passwordHash);
return $adminId;
}
/**
* Remember a password hash for further usage.
*
* @param int $adminId
* @param string $passwordHash
* @return void
*/
private function trackPassword($adminId, $passwordHash)
{
$this->connection->insert(
$this->getTableName('admin_passwords'),
[
'user_id' => $adminId,
'password_hash' => $passwordHash,
'last_updated' => time()
]
);
}
/**
* Validates that the username and email both match the user,
* and that password exists and is different from user name.
*
* @return void
* @throws \Exception If the username and email do not both match data provided to install
* @throws \Exception If password is empty and if password is the same as the user name
*/
public function validateUserMatches()
{
if (empty($this->data[self::KEY_PASSWORD])) {
throw new \Exception(
'"Password" is required. Enter and try again.'
);
}
if (strcasecmp($this->data[self::KEY_PASSWORD], $this->data[self::KEY_USER]) == 0) {
throw new \Exception(
'Password cannot be the same as the user name.'
);
}
try {
$result = $this->connection->fetchRow(
"SELECT user_id, username, email FROM {$this->getTableName('admin_user')} "
. "WHERE username = :username OR email = :email",
['username' => $this->data[self::KEY_USER], 'email' => $this->data[self::KEY_EMAIL]]
);
} catch (\Exception $e) {
return; // New installation, no need to validate existing users.
}
$email = $result['email'];
$username = $result['username'];
if ((strcasecmp($email, $this->data[self::KEY_EMAIL]) == 0) &&
(strcasecmp($username, $this->data[self::KEY_USER]) != 0)) {
// email matched but username did not
throw new \Exception(
'An existing user has the given email but different username. '
. 'Username and email both need to match an existing user or both be new.'
);
}
if ((strcasecmp($username, $this->data[self::KEY_USER]) == 0) &&
(strcasecmp($email, $this->data[self::KEY_EMAIL]) != 0)) {
// username matched but email did not
throw new \Exception(
'An existing user has the given username but different email. '
. 'Username and email both need to match an existing user or both be new.'
);
}
}
/**
* Creates the admin user role if one does not exist.
*
* Do nothing if a role already exists for this user
*
* @param int $adminId User id of administrator to set role for
* @return void
*/
private function saveAdminUserRole($adminId)
{
$result = $this->connection->fetchRow(
'SELECT * FROM ' . $this->getTableName('authorization_role') . ' ' .
'WHERE user_id = :user_id AND user_type = :user_type',
['user_id' => $adminId, 'user_type' => UserContextInterface::USER_TYPE_ADMIN]
);
if (empty($result)) {
// No user role exists for this user id, create it
$adminRoleData = [
'parent_id' => $this->retrieveAdministratorsRoleId(),
'tree_level' => 2,
'role_type' => User::ROLE_TYPE,
'user_id' => $adminId,
'user_type' => UserContextInterface::USER_TYPE_ADMIN,
'role_name' => $this->data[self::KEY_USER],
];
$this->connection->insert($this->getTableName('authorization_role'), $adminRoleData);
}
}
/**
* Gets the "Administrators" role id, the special role created by data fixture in Authorization module.
*
* @return int The id of the Administrators role
* @throws \Exception If Administrators role not found or problem connecting with database.
*/
private function retrieveAdministratorsRoleId()
{
// Get Administrators role id to use as parent_id
$administratorsRoleData = [
'parent_id' => 0,
'tree_level' => 1,
'role_type' => Group::ROLE_TYPE,
'user_id' => 0,
'user_type' => UserContextInterface::USER_TYPE_ADMIN,
'role_name' => 'Administrators',
];
$result = $this->connection->fetchRow(
'SELECT * FROM ' . $this->getTableName('authorization_role') . ' ' .
'WHERE parent_id = :parent_id AND tree_level = :tree_level AND role_type = :role_type AND ' .
'user_id = :user_id AND user_type = :user_type AND role_name = :role_name',
$administratorsRoleData
);
if (empty($result)) {
throw new \Exception('No Administrators role was found, data fixture needs to be run');
} else {
// Found at least one, use first
return $result['role_id'];
}
}
/**
* Take table with prefix without loading modules
*
* @param string $table
* @return string
*/
private function getTableName($table)
{
if (!empty($this->data[self::KEY_PREFIX])) {
return $this->connection->getTableName($this->data[self::KEY_PREFIX] . $table);
}
return $this->connection->getTableName($table);
}
}