Files
moonwell-web/app/Http/Controllers/Api/LauncherRegistrationController.php

126 lines
5.9 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Exceptions\DuplicateGameAccountException;
use App\Exceptions\InviteCodeException;
use App\Http\Controllers\Controller;
use App\Http\Requests\RegisterGameAccountRequest;
use App\Services\AzerothCoreAccountRegistrar;
use App\Services\InviteCodeService;
use Illuminate\Http\JsonResponse;
use OpenApi\Attributes as OA;
use Throwable;
class LauncherRegistrationController extends Controller
{
#[OA\Post(
path: '/api/launcher/register',
summary: 'Зарегистрировать игровой аккаунт',
description: 'Создаёт игровой аккаунт AzerothCore. Инвайт-код обязателен, если на сервере включена регистрация по приглашениям.',
tags: ['Launcher Auth'],
requestBody: new OA\RequestBody(
required: true,
content: new OA\JsonContent(
required: ['username', 'email', 'password', 'password_confirmation', 'terms'],
properties: [
new OA\Property(property: 'username', type: 'string', minLength: 3, maxLength: 32, pattern: '^[A-Za-z0-9]+$', example: 'Player'),
new OA\Property(property: 'email', type: 'string', format: 'email', maxLength: 255, example: 'player@example.com'),
new OA\Property(property: 'invite_code', type: 'string', minLength: 6, maxLength: 32, nullable: true, example: 'ABCD-EFGH-IJKL'),
new OA\Property(property: 'password', type: 'string', minLength: 8, maxLength: 32, example: 'Secret123'),
new OA\Property(property: 'password_confirmation', type: 'string', minLength: 8, maxLength: 32, example: 'Secret123'),
new OA\Property(property: 'terms', type: 'boolean', example: true, description: 'Согласие с правилами сервера и пользовательским соглашением'),
],
),
),
responses: [
new OA\Response(
response: 201,
description: 'Аккаунт создан',
content: new OA\JsonContent(
properties: [
new OA\Property(property: 'message', type: 'string', example: 'Игровой аккаунт успешно создан.'),
new OA\Property(
property: 'account',
properties: [
new OA\Property(property: 'id', type: 'integer', example: 77),
new OA\Property(property: 'username', type: 'string', example: 'PLAYER'),
],
type: 'object',
),
],
),
),
new OA\Response(
response: 422,
description: 'Ошибка валидации, занятый логин или неверный инвайт-код',
content: new OA\JsonContent(
properties: [
new OA\Property(property: 'message', type: 'string', example: 'Такой игровой аккаунт уже существует.'),
new OA\Property(
property: 'errors',
type: 'object',
additionalProperties: new OA\AdditionalProperties(
type: 'array',
items: new OA\Items(type: 'string'),
),
),
],
),
),
new OA\Response(
response: 500,
description: 'Внутренняя ошибка регистрации',
content: new OA\JsonContent(
properties: [
new OA\Property(property: 'message', type: 'string', example: 'Не удалось создать аккаунт. Попробуй снова позже.'),
],
),
),
new OA\Response(response: 429, description: 'Слишком много запросов'),
],
)]
public function store(
RegisterGameAccountRequest $request,
AzerothCoreAccountRegistrar $registrar,
InviteCodeService $inviteCodes,
): JsonResponse {
try {
$register = fn (): array => $registrar->register(
$request->string('username')->toString(),
$request->string('email')->toString(),
$request->string('password')->toString(),
);
$account = config('moonwell.registration.require_invite_code')
? $inviteCodes->redeemForRegistration(
$request->string('invite_code')->toString(),
$request->string('username')->toString(),
$register,
)
: $register();
} catch (DuplicateGameAccountException|InviteCodeException $exception) {
return response()->json([
'message' => $exception->getMessage(),
'errors' => [
$exception->field => [$exception->getMessage()],
],
], 422);
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => 'Не удалось создать аккаунт. Попробуй снова позже.',
], 500);
}
return response()->json([
'message' => 'Игровой аккаунт успешно создан.',
'account' => [
'id' => $account['id'],
'username' => $account['username'],
],
], 201);
}
}