Files
moonwell-web/app/Services/AzerothCoreAccountRegistrar.php
2026-03-13 23:33:35 +04:00

102 lines
3.6 KiB
PHP

<?php
namespace App\Services;
use App\Exceptions\DuplicateGameAccountException;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
class AzerothCoreAccountRegistrar
{
public function __construct(private readonly AzerothCoreSrpService $srp)
{
}
/**
* @return array{id: int, username: string}
*/
public function register(string $username, string $email, string $password): array
{
$normalizedUsername = $this->srp->normalizeUsername($username);
$normalizedPassword = $this->srp->normalizePassword($password);
$normalizedEmail = $this->srp->normalizeEmail($email);
[$saltHex, $verifierHex] = $this->srp->makeRegistrationData($normalizedUsername, $normalizedPassword);
$connection = DB::connection(config('moonwell.auth_connection'));
return $connection->transaction(function () use (
$connection,
$normalizedEmail,
$normalizedUsername,
$saltHex,
$verifierHex,
): array {
if ($this->accountExists($connection, 'username', $normalizedUsername)) {
throw DuplicateGameAccountException::forUsername();
}
if (
config('moonwell.registration.enforce_unique_email')
&& $normalizedEmail !== ''
&& $this->accountExists($connection, 'email', $normalizedEmail)
) {
throw DuplicateGameAccountException::forEmail();
}
try {
$connection->insert(
'INSERT INTO account (username, salt, verifier, expansion, reg_mail, email, joindate) VALUES (?, UNHEX(?), UNHEX(?), ?, ?, ?, ?)',
[
$normalizedUsername,
$saltHex,
$verifierHex,
config('moonwell.registration.expansion'),
$normalizedEmail,
$normalizedEmail,
now()->toDateTimeString(),
],
);
} catch (QueryException $exception) {
if ($this->isDuplicateKeyException($exception)) {
throw DuplicateGameAccountException::forUsername();
}
throw $exception;
}
$accountId = (int) $connection->getPdo()->lastInsertId();
$connection->insert(
'INSERT IGNORE INTO realmcharacters (realmid, acctid, numchars) SELECT id, ?, 0 FROM realmlist',
[$accountId],
);
$connection->statement(
'INSERT INTO account_access (id, gmlevel, RealmID, comment) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE gmlevel = VALUES(gmlevel), comment = VALUES(comment)',
[
$accountId,
config('moonwell.registration.gmlevel'),
config('moonwell.registration.realm_id'),
config('moonwell.registration.access_comment'),
],
);
return [
'id' => $accountId,
'username' => $normalizedUsername,
];
}, 3);
}
private function accountExists(ConnectionInterface $connection, string $column, string $value): bool
{
return $connection->table('account')->where($column, $value)->exists();
}
private function isDuplicateKeyException(QueryException $exception): bool
{
return (string) $exception->getCode() === '23000';
}
}