mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 01:08:56 +00:00
Add logging for failed registration
This commit is contained in:
@@ -128,6 +128,14 @@ class RegisterController extends Controller
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->logRegistrationFailure(
|
||||
$request,
|
||||
'validation_failed',
|
||||
'The registration request failed validation.',
|
||||
'warning',
|
||||
['validation_errors' => $validator->errors()->toArray()]
|
||||
);
|
||||
|
||||
return redirect()->back()
|
||||
->withErrors($validator)
|
||||
->withInput($request->except('password', 'password_confirmation'));
|
||||
@@ -146,7 +154,8 @@ class RegisterController extends Controller
|
||||
if ($existingUser && $existingUser->trashed()) {
|
||||
return $this->redirectBackWithRegistrationError(
|
||||
$request,
|
||||
'This email address belongs to a deactivated account. Please contact us if you need help reactivating it.'
|
||||
'This email address belongs to a deactivated account. Please contact us if you need help reactivating it.',
|
||||
'deactivated_account'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -171,7 +180,8 @@ class RegisterController extends Controller
|
||||
if (! empty($invitation->email) && ! $this->emailsMatch($invitation->email, $email)) {
|
||||
return $this->redirectBackWithRegistrationError(
|
||||
$request,
|
||||
'The email address you entered does not match the invitation. Please use the invited email address to register.'
|
||||
'The email address you entered does not match the invitation. Please use the invited email address to register.',
|
||||
'invitation_email_mismatch'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -203,16 +213,15 @@ class RegisterController extends Controller
|
||||
}
|
||||
});
|
||||
} catch (Throwable $exception) {
|
||||
Log::error('User registration failed', [
|
||||
'username' => $userName,
|
||||
'email' => $email,
|
||||
'ip' => $request->ip(),
|
||||
'error' => $exception->getMessage(),
|
||||
]);
|
||||
|
||||
return $this->redirectBackWithRegistrationError(
|
||||
$request,
|
||||
'We could not complete your registration right now. Please try again in a few minutes. If the problem continues, contact support.'
|
||||
'We could not complete your registration right now. Please try again in a few minutes. If the problem continues, contact support.',
|
||||
'unexpected_exception',
|
||||
'error',
|
||||
[
|
||||
'error' => $exception->getMessage(),
|
||||
'exception' => $exception::class,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,6 +232,11 @@ class RegisterController extends Controller
|
||||
}
|
||||
|
||||
$error = 'Invalid or expired invitation token!';
|
||||
$this->logRegistrationFailure(
|
||||
$request,
|
||||
'invalid_or_expired_invitation',
|
||||
'The registration attempt used an invalid or expired invitation token.'
|
||||
);
|
||||
break;
|
||||
|
||||
case 'view':
|
||||
@@ -328,14 +342,47 @@ class RegisterController extends Controller
|
||||
return $invitation !== null;
|
||||
}
|
||||
|
||||
private function redirectBackWithRegistrationError(Request $request, string $message): RedirectResponse
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
private function redirectBackWithRegistrationError(
|
||||
Request $request,
|
||||
string $message,
|
||||
string $reason = 'registration_failed',
|
||||
string $level = 'warning',
|
||||
array $context = []
|
||||
): RedirectResponse {
|
||||
$this->logRegistrationFailure($request, $reason, $message, $level, $context);
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->withErrors(['registration' => $message])
|
||||
->withInput($request->except('password', 'password_confirmation'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
private function logRegistrationFailure(
|
||||
Request $request,
|
||||
string $reason,
|
||||
string $message,
|
||||
string $level = 'warning',
|
||||
array $context = []
|
||||
): void {
|
||||
$logContext = array_merge([
|
||||
'reason' => $reason,
|
||||
'message' => $message,
|
||||
'username' => $request->input('username'),
|
||||
'email' => $request->input('email'),
|
||||
'ip' => $request->ip(),
|
||||
'registration_status' => Settings::settingValue('registerstatus'),
|
||||
'has_invite_code' => $request->filled('invitecode') || $request->filled('token'),
|
||||
], $context);
|
||||
|
||||
Log::channel('registration')->{$level}("Registration attempt failed: {$reason}", $logContext);
|
||||
}
|
||||
|
||||
private function emailsMatch(string $firstEmail, string $secondEmail): bool
|
||||
{
|
||||
return strcasecmp(trim($firstEmail), trim($secondEmail)) === 0;
|
||||
|
||||
+11
-2
@@ -38,7 +38,7 @@ return [
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => 'debug',
|
||||
'handler' => SyslogUdpHandler::class,
|
||||
'handler' => Monolog\Handler\SyslogUdpHandler::class,
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
'port' => env('PAPERTRAIL_PORT'),
|
||||
@@ -46,7 +46,7 @@ return [
|
||||
],
|
||||
'stderr' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => StreamHandler::class,
|
||||
'handler' => Monolog\Handler\StreamHandler::class,
|
||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||
'with' => [
|
||||
'stream' => 'php://stderr',
|
||||
@@ -87,6 +87,15 @@ return [
|
||||
'permission' => 0775,
|
||||
'locking' => false,
|
||||
],
|
||||
'registration' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/registration.log'),
|
||||
'level' => 'debug',
|
||||
'days' => 7,
|
||||
'bubble' => true,
|
||||
'permission' => 0775,
|
||||
'locking' => false,
|
||||
],
|
||||
'crc_oso' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/crc_oso.log'),
|
||||
|
||||
@@ -10,7 +10,9 @@ use Illuminate\Contracts\Validation\UncompromisedVerifier;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Mockery;
|
||||
use Mockery\MockInterface;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -132,6 +134,26 @@ class RegisterControllerTest extends TestCase
|
||||
|
||||
public function test_registration_failure_shows_explanation_for_deactivated_account(): void
|
||||
{
|
||||
Log::partialMock();
|
||||
|
||||
$registrationLogger = Mockery::mock();
|
||||
Log::shouldReceive('channel')
|
||||
->once()
|
||||
->with('registration')
|
||||
->andReturn($registrationLogger);
|
||||
|
||||
$registrationLogger->shouldReceive('warning')
|
||||
->once()
|
||||
->with(
|
||||
'Registration attempt failed: deactivated_account',
|
||||
Mockery::on(function (array $context): bool {
|
||||
return $context['reason'] === 'deactivated_account'
|
||||
&& $context['email'] === 'disabled@example.com'
|
||||
&& $context['username'] === 'freshmember'
|
||||
&& $context['registration_status'] === 0;
|
||||
})
|
||||
);
|
||||
|
||||
DB::table('users')->insert([
|
||||
'username' => 'oldmember',
|
||||
'email' => 'disabled@example.com',
|
||||
@@ -158,4 +180,49 @@ class RegisterControllerTest extends TestCase
|
||||
'registration' => 'This email address belongs to a deactivated account. Please contact us if you need help reactivating it.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_registration_exception_is_logged_to_registration_channel(): void
|
||||
{
|
||||
Log::partialMock();
|
||||
|
||||
$registrationLogger = Mockery::mock();
|
||||
Log::shouldReceive('channel')
|
||||
->once()
|
||||
->with('registration')
|
||||
->andReturn($registrationLogger);
|
||||
|
||||
$registrationLogger->shouldReceive('error')
|
||||
->once()
|
||||
->with(
|
||||
'Registration attempt failed: unexpected_exception',
|
||||
Mockery::on(function (array $context): bool {
|
||||
return $context['reason'] === 'unexpected_exception'
|
||||
&& $context['email'] === 'broken@example.com'
|
||||
&& $context['username'] === 'brokenmember'
|
||||
&& $context['exception'] === \RuntimeException::class
|
||||
&& $context['registration_status'] === 0;
|
||||
})
|
||||
);
|
||||
|
||||
$this->partialMock(RegisterController::class, function (MockInterface $mock): void {
|
||||
$mock->shouldAllowMockingProtectedMethods();
|
||||
$mock->shouldReceive('create')
|
||||
->once()
|
||||
->andThrow(new \RuntimeException('Simulated registration failure'));
|
||||
});
|
||||
|
||||
$response = $this->from(route('register'))->post(route('register.post'), [
|
||||
'action' => 'submit',
|
||||
'username' => 'brokenmember',
|
||||
'email' => 'broken@example.com',
|
||||
'password' => 'ValidPass1!',
|
||||
'password_confirmation' => 'ValidPass1!',
|
||||
'terms' => 'on',
|
||||
]);
|
||||
|
||||
$response->assertRedirect(route('register'));
|
||||
$response->assertSessionHasErrors([
|
||||
'registration' => 'We could not complete your registration right now. Please try again in a few minutes. If the problem continues, contact support.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user