PHP code example of pijler / user-devices

1. Go to this page and download the library: Download pijler/user-devices library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

pijler / user-devices example snippets


// config/user-devices.php
return [
    'events' => [
        'failed' => true,          // Track failures, notify when new device
        'attempting' => false,     // Track attempts, notify when new device
        'authenticated' => true,   // Save device + send new login notification
    ],
    'credential_key' => 'email',   // Key to find user from credentials (attempting/failed)
];

use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\URL;
use UserDevices\DeviceCreator;
use UserDevices\Notifications\AuthenticatedLoginNotification;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Use custom user model
        DeviceCreator::useUserModel(CustomUser::class);

        // Use custom user device model
        DeviceCreator::useUserDeviceModel(CustomUserDevice::class);

        // Customize user agent generation
        DeviceCreator::userAgentUsing(fn ($userAgent) => substr($userAgent, 0, 255));

        // Control when to send notifications (e.g. disable in local/staging)
        DeviceCreator::shouldSendNotificationUsing(function ($user, $device) {
            return ! app()->environment('local');
        });

        // Resolve location from IP (optional)
        DeviceCreator::resolveLocationUsing(function (string $ip) {
            $geo = geoip($ip);
            return $geo->city ? "{$geo->city}, {$geo->country}" : $geo->country;
        });

        // Customize the notification email
        AuthenticatedLoginNotification::toMailUsing(function ($notifiable, $device) {
            $expire = Config::get('auth.verification.expire', 60);

            $blockUrl = URL::temporarySignedRoute(
                name: 'user-devices.block',
                expiration: Carbon::now()->addMinutes($expire),
                parameters: [
                    'id' => $device->getKey(),
                    'hash' => sha1($device->getKey()),
                ],
            );

            return (new MailMessage)
                ->subject('New device detected')
                ->line('We detected a new login to your account.')
                ->action('Block device', $blockUrl);
        });

        // Customize the block device URL
        AuthenticatedLoginNotification::createBlockUrlUsing(function ($device) {
            return URL::temporarySignedRoute(
                name: 'your-custom-route-name',
                expiration: Carbon::now()->addMinutes(120),
                parameters: [
                    'id' => $device->getKey(),
                    'hash' => sha1($device->getKey()),
                ],
            );
        });
    }
}

use Illuminate\Notifications\Notifiable;
use UserDevices\Traits\HasUserDevices;

class User extends Authenticatable
{
    use HasUserDevices;
    use Notifiable;
}

use UserDevices\DeviceCreator;

DeviceCreator::ignoreListener();

DeviceCreator::ignoreNotification();

DeviceCreator::shouldSendNotificationUsing(fn () => false);
DeviceCreator::shouldSendNotificationUsing(fn ($user, $device) => ! $user->isAdmin());
DeviceCreator::shouldSendNotificationUsing(fn ($user, $device) => app()->environment('production'));

use UserDevices\Http\Requests\BlockDeviceRequest;

Route::get('/devices/block/{id}/{hash}', function (BlockDeviceRequest $request) {
    $request->fulfill();

    return redirect()->route('home')->with('message', 'Device blocked successfully.');
})->middleware(['signed', 'throttle:6,1'])->name('user-devices.block');

// In your login logic, after resolving the user from credentials (e.g. email)
$user = User::where('email', $request->email)->first();

if ($user && $user->isCurrentDeviceBlocked()) {
    return response()->json(['message' => 'This device has been blocked.'], 423);
}

// Proceed with login attempt...

public function authorize(): bool
{
    $user = User::where('email', $this->email)->first();
    
    return ! ($user && $user->isCurrentDeviceBlocked());
}

Route::middleware(['auth', 'check.device'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
});

use UserDevices\Models\UserDevice;

// Get user's devices
$devices = $user->userDevices;

// Block a device (invalidates session if session_id is set)
$device = UserDevice::find($id);
$device->block();

// Unblock a device
$device->unblock();

// Block by ID (static)
UserDevice::markAsBlocked($id);

// Unblock by ID (static)
UserDevice::markAsUnblocked($id);

$user->sendFailedLoginNotification($device);
$user->sendAttemptingLoginNotification($device);
$user->sendAuthenticatedLoginNotification($device);

use UserDevices\Notifications\AttemptingLoginNotification;
use UserDevices\Notifications\FailedLoginNotification;

AttemptingLoginNotification::toMailUsing(fn ($notifiable, $device) => (new MailMessage)
    ->subject('Login attempt')->line("IP: {$device->ip_address}"));

AttemptingLoginNotification::createBlockUrlUsing(fn ($device) => URL::temporarySignedRoute(/* ... */));

FailedLoginNotification::toMailUsing(fn ($notifiable, $device) => (new MailMessage)
    ->subject('Failed login')->line("IP: {$device->ip_address}"));

FailedLoginNotification::createBlockUrlUsing(fn ($device) => URL::temporarySignedRoute(/* ... */));

// Configuration
DeviceCreator::useUserModel(string $model): void
DeviceCreator::useUserDeviceModel(string $model): void
DeviceCreator::userAgentUsing(Closure $callback): void
DeviceCreator::resolveLocationUsing(Closure $callback): void  // (string $ip) => ?string
DeviceCreator::shouldSendNotificationUsing(Closure $callback): void  // (user, device) => bool

// Request context (call before authentication)
DeviceCreator::ignoreListener(): void     // Skip saving the device for the current request
DeviceCreator::ignoreNotification(): void // Skip the new login notification for the current request

// Relationships
$device->user(): BelongsTo

// Actions
$device->block(): void   // Also invalidates session when session_id is set
$device->unblock(): void

// Static methods
UserDevice::markAsBlocked(mixed $id): void
UserDevice::markAsUnblocked(mixed $id): void

// Methods available on model
$model->userDevices(): HasMany
$model->isCurrentDeviceBlocked(): bool  // Check if current request's device is blocked (use before login)
$model->sendFailedLoginNotification(UserDevice $device): void
$model->sendAttemptingLoginNotification(UserDevice $device): void
$model->sendAuthenticatedLoginNotification(UserDevice $device): void

AuthenticatedLoginNotification::toMailUsing(Closure $callback): void
AuthenticatedLoginNotification::createBlockUrlUsing(Closure $callback): void

AttemptingLoginNotification::toMailUsing(Closure $callback): void
AttemptingLoginNotification::createBlockUrlUsing(Closure $callback): void

FailedLoginNotification::toMailUsing(Closure $callback): void
FailedLoginNotification::createBlockUrlUsing(Closure $callback): void

$request->fulfill(): void
$request->getDevice(): ?UserDevice
bash
php artisan vendor:publish --tag=user-devices-config
bash
php artisan vendor:publish --tag=user-devices-migrations
bash
php artisan migrate