You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: DATABASE.md
+36-49Lines changed: 36 additions & 49 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,50 +1,44 @@
1
1
# Model customization
2
2
3
-
You can further customize the package Models using the `customize()` method with a callback that receives the freshly instanced model instance. For example, you may want to hide some attributes, or change the table and connection the Model by default. Preferably, you would do this in your `bootstrap/app.php`.
3
+
Most of the time you will want to change the table name of the Model, maybe because it collides with another. Use the `customize()` method with the table name. Preferably, you would do this in your `bootstrap/app.php`.
4
4
5
5
```php
6
6
use Illuminate\Foundation\Application;
7
-
use Illuminate\Foundation\Configuration\Exceptions;
8
-
use Illuminate\Foundation\Configuration\Middleware;
> For your convenience, the Migration will automatically pick up the table and connection you set in the Model.
26
-
27
-
## Changing the table name
16
+
You can further customize the Models included in this package with a callback that receives a Model instance. This method is always executed when instancing a Model.
28
17
29
-
To change the table the model should use, use the customize method inside the `->booted(...)` callback in `bootstrap/app.php` or within the `boot` method of a `ServiceProvider`.
18
+
For example, you may hide some attributes or change the table and connection the Model by default.
> There is no need to alter the Model migration if you change the table. The migration automatically picks up the table and connection you set in through the `customize()` method.
38
34
>
39
-
> If you're migrating from 2.x to 3.x, the property `TwoFactorAuthentication::$useTable = 'my_custom_table';` is deprecated. Instead, set the custom table name using the `customize` method as shown above.
40
-
41
35
42
36
# Migration customization
43
37
44
38
The library you have installed comes with a very hands-off approach for migrations. If you check the new migrations published at `database/migrations`, you will find something very similar to this:
@@ -54,7 +48,7 @@ Worry not, the migration will still work. It has been _simplified_ for easy cust
54
48
55
49
## Adding columns
56
50
57
-
To add columns to the migration, add a callback to the `with()` method. The callback will receive the table blueprint so you can modify the table while it's being created.
51
+
To add columns to the migration, add a callback to the `with()` method. The callback will receive the table blueprint, so you can modify the table before it is created. New columns will be appended to the table blueprint.
> The columns you add will be created _after_ the package adds its own columns. In other words, these will be set at the end of the table.
72
-
73
63
### Relationships
74
64
75
-
If the package supports it, you may add relationships through their proper migration columns. For example, if we want to add the `driver` relationship to the model, we can use the native `resolveRelationUsing()` on your `bootstrap/app.php()`.
65
+
If the package supports it, you may add relationships through their proper migration columns. For example, if we want to add the `car` relationship to the package Model, we can use the native `resolveRelationUsing()` on your `bootstrap/app.php()`.
76
66
77
67
```php
68
+
use App\Models\Driver;
78
69
use Illuminate\Foundation\Application;
79
-
use Illuminate\Foundation\Configuration\Exceptions;
80
-
use Illuminate\Foundation\Configuration\Middleware;
In the published package migration, you should be able to add the required column to connect your model like normal. In this case, we can use the [`foreignIdFor()`](https://laravel.com/docs/migrations#column-method-foreignIdFor) method to safely set the proper column type.
81
+
In the published package migration, you should be able to add the required column to connect your model like usual. In this case, we can use the [`foreignIdFor()`](https://laravel.com/docs/migrations#column-method-foreignIdFor) method to safely set the proper column name and type.
If you need to execute logic after creating the table, or before dropping it, use the `afterUp()` and `beforeDown()` methods, respectively.
97
+
If you need to execute logic _after_ creating the table, or _before_ dropping it, use the `afterUp()` and `beforeDown()` methods, respectively.
109
98
110
99
```php
111
100
use Illuminate\Database\Schema\Blueprint;
112
-
use Laragear\Package\Models\Car;
101
+
use Vendor\Package\Models\Car;
113
102
114
103
return Car::migration()
115
104
->afterUp(function (Blueprint $table) {
@@ -120,27 +109,25 @@ return Car::migration()
120
109
});
121
110
```
122
111
123
-
## Morphs
112
+
###Morphs
124
113
125
-
This package _may_ create a morph relation automatically, with the intent to easily handle default relationship across multiple models. For example, a morph migration to support an `owner` being either one of your models `Company` or `Person`.
114
+
Some packages will create a morph relation automaticallyto easily handle the default relationship across multiple models. For example, a morph migration to support an `owner` being either one of your models `user` or `business`.
126
115
127
116
```php
128
-
use Laragear\Package\Models\Car;
117
+
use Vendor\Package\Models\Car;
129
118
130
119
$car = Car::find(1);
131
120
132
-
$owners = $car->owner; // App/Models/Company or App/Models/Person
121
+
$owner = $driver->owner; // App/Models/User or App/Models/Business
133
122
```
134
123
135
-
You may find yourself with youur models using a primary key type, different to the type used by the library models. For example, your `Company` or `Person` models using UUID, while the migration morph type uses integers.
124
+
You may find yourself with models that use UUID, ULID or other types of primary keys, but with a migration that creates morphs for integer primary keys.
136
125
137
-
If that's your case, you can change the library morph type with the `morph...` property access (preferably), or the `morph()` method with `numeric`, `uuid` or `ulid` if you need to also set an index name (in case your database engine doesn't play nice with large ones).
138
-
139
-
For example, you can change the morph type of the `Car` migration to match the UUID type for the `Company` and `Person` models.
126
+
You can change the morph type with the `morph...` property access preferably, or the `morph()` method with `numeric`, `uuid` or `ulid` if you need to also set an index name (in case your database engine doesn't play nice with large ones).
Copy file name to clipboardExpand all lines: README.md
+134-5Lines changed: 134 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,13 +38,16 @@ Your support allows me to keep this package free, up-to-date and maintainable. A
38
38
39
39
## Requirements
40
40
41
-
* Laravel 11 or later
41
+
* PHP 8.3 or later
42
+
* Laravel 12 or later
42
43
43
44
## Installation
44
45
45
46
Fire up Composer and require this package in your project.
46
47
47
-
composer require laragear/two-factor
48
+
```shell
49
+
composer require laragear/two-factor
50
+
```
48
51
49
52
That's it.
50
53
@@ -105,9 +108,9 @@ To enable Two-Factor Authentication for the User, he must sync the Shared Secret
105
108
106
109
> [!TIP]
107
110
>
108
-
> Free Authenticator Apps, in no particular order, are [iOS Authenticator](https://www.apple.com/ios/), [FreeOTP](https://freeotp.github.io/), [Authy](https://authy.com/), [2FAS](https://2fas.com/), [2Stable Authenticator](https://authenticator.2stable.com/), [Step-two](https://steptwo.app/), [BinaryRoot Authenticator](https://www.binaryboot.com/totp-authenticator), [Google](https://apps.apple.com/app/google-authenticator/id388497605)[Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en), and [Microsoft Authenticator](https://www.microsoft.com/en-us/account/authenticator), to name a few.
111
+
> Free Authenticator Apps, in no particular order, are [iOS Authenticator](https://www.apple.com/ios/), [FreeOTP](https://freeotp.github.io/), [Authy](https://authy.com/), [2FAS](https://2fas.com/), [2Stable Authenticator](https://authenticator.2stable.com/), [Step-two](https://steptwo.app/), [BinaryRoot Authenticator](https://www.binaryboot.com/totp-authenticator) and [Google](https://apps.apple.com/app/google-authenticator/id388497605)[Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en).
109
112
110
-
To start, generate the needed data using the `createTwoFactorAuth()` method. This returns a serializable _Shared Secret_ that you can show to the User as a string or QR Code (encoded as SVG) in your view.
113
+
To start, generate the necessary data using the `createTwoFactorAuth()` method. This returns a serializable _Shared Secret_ that you can show to the User as a string or QR Code (encoded as SVG) in your view.
111
114
112
115
```php
113
116
use Illuminate\Http\Request;
@@ -406,6 +409,109 @@ Route::get('api/important-token', function () {
This library includes a global throttling middleware. It will trigger a TOTP confirmation once a number of Requests done to the application exceed a default threshold.
415
+
416
+
To enable the global middleware, set the `OTP_THROTTLE` environment variable to `true`.
417
+
418
+
```dotenv
419
+
OTP_THROTTLE
420
+
```
421
+
422
+
Alternatively, you can enable it globally and also set the threshold using `{tries},{decay}` notation. For example, to change the threshold to a maximum of 3 requests each 15 seconds.
423
+
424
+
```dotenv
425
+
OTP_THROTTLE=3,15
426
+
```
427
+
428
+
You may configure the global throttling additional features in the [configuration file](#throttling).
429
+
430
+
> [!IMPORTANT]
431
+
>
432
+
> The Throttling Middleware uses your application [Rate Limiter](https://laravel.com/docs/12.x/rate-limiting).
433
+
434
+
#### Using a custom throttle key
435
+
436
+
By default, the key to throttle the request is generated using the IP.
437
+
438
+
You may want to create your own key based on the request by setting a callback in the `$key` static property of the `Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor` class, in your `bootstrap/app.php` file. For example, you may add a string to differentiate multiple users from the same IP.
439
+
440
+
```php
441
+
use Illuminate\Foundation\Application;
442
+
use Illuminate\Http\Request;
443
+
use Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor;
444
+
445
+
return Application::configure()
446
+
->booted(function () {
447
+
ThrottleWithTwoFactor::$key = function (Request $request) {
#### Determining if the request should be throttled
455
+
456
+
You may programmatically throttle requests by setting a callback in the `$shouldThrottle` static property of the `Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor` class, in your `bootstrap/app.php` file.
457
+
458
+
```php
459
+
use Illuminate\Foundation\Application;
460
+
use Illuminate\Http\Request;
461
+
use Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor;
462
+
463
+
return Application::configure()
464
+
->booted(function () {
465
+
ThrottleWithTwoFactor::$shouldThrottle = function (Request $request) {
466
+
return $request->user()->isNotVip();
467
+
}
468
+
})
469
+
->create();
470
+
```
471
+
472
+
Inside the function, you can use the method `clearAttempts()` of the middleware instance present as a second parameter in the callback to clear the attempts of the given request.
473
+
474
+
```php
475
+
use Illuminate\Foundation\Application;
476
+
use Illuminate\Http\Request;
477
+
use Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor;
478
+
479
+
return Application::configure()
480
+
->booted(function () {
481
+
ThrottleWithTwoFactor::$shouldThrottle = function (Request $request, ThrottleWithTwoFactor $instance) {
482
+
if ($request->user()->impersontedByAdmin()) {
483
+
$instance->clearAttempts($request);
484
+
}
485
+
486
+
return $request->user()->isNotVip();
487
+
}
488
+
})
489
+
->create();
490
+
```
491
+
492
+
493
+
#### Custom Rate Limiter Cache
494
+
495
+
You may want to use a custom Cache Store to use with the middleware. This requires instructing the Container to give a custom Rate Limiter created by you when resolving the `Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor` class.
496
+
497
+
This can be done in the `bootstrap/app.php` with the `registered()` method and [Contextual Binding](https://laravel.com/docs/12.x/container#contextual-binding).
498
+
499
+
```php
500
+
use Illuminate\Cache\RateLimiter;
501
+
use Illuminate\Foundation\Application;
502
+
use Laragear\TwoFactor\Http\Middleware\ThrottleWithTwoFactor;
503
+
504
+
return Application::configure()
505
+
->registered(function (Application $app) {
506
+
$app->when(ThrottleWithTwoFactor::class)
507
+
->needs(RateLimiter::class)
508
+
->give(function () use ($app) {
509
+
return new RateLimiter(cache()->store('memcached'))
510
+
});
511
+
})
512
+
->create();
513
+
```
514
+
409
515
## Validation
410
516
411
517
Sometimes you may want to manually trigger a TOTP validation in any part of your application for the authenticated user. You can validate a TOTP code for the authenticated user using the `topt` rule.
@@ -421,7 +527,7 @@ public function checkTotp(Request $request)
421
527
}
422
528
```
423
529
424
-
This rule will succeed only if the user is authenticated, it has Two-Factor Authentication enabled, and the code is correct or is a recovery code.
530
+
This rule will succeed only if the user is authenticated, it has Two-Factor Authentication enabled, and the code is correct or is a recovery code.
425
531
426
532
> [!TIP]
427
533
>
@@ -495,6 +601,11 @@ return [
495
601
'size' => 400,
496
602
'margin' => 4
497
603
],
604
+
'throttle' => [
605
+
'enable' => env('OTP_THROTTLE'),
606
+
'amount' => [6, 60],
607
+
'route' => '2fa.confirm'
608
+
]
498
609
];
499
610
```
500
611
@@ -639,6 +750,24 @@ return [
639
750
640
751
This controls the size and margin used to create the QR Code, which are created as SVG.
641
752
753
+
### Throttling
754
+
755
+
```php
756
+
return [
757
+
'throttle' => [
758
+
'enable' => env('OTP_THROTTLE', false),
759
+
'tries' => [6, 60],
760
+
'session_key' => '_totp_throttle',
761
+
'route' => '2fa.throttle'
762
+
'lifetime' => 10
763
+
],
764
+
];
765
+
```
766
+
767
+
This configures the [throttling global middleware](#throttling-middleware). The most important part is the route to redirect the user once the application throttles the user request, and where in the session to save this data.
768
+
769
+
The `lifetime` key sets how many minutes to "bypass" the throttler after the user has been already throttled.
770
+
642
771
## Custom TOTP Label
643
772
644
773
You may change how your model creates a TOTP Label, which is shown to the user on its authenticator, using the `getTwoFactorIssuer()` and `getTwoFactorUserIdentifier()` methods of your user.
0 commit comments