Initial commit

refatoracoes-metodos
Pablo 10 months ago
commit 2811122cfa

30
.gitignore vendored

@ -0,0 +1,30 @@
# Laravel & PHP
/vendor
/node_modules
/public/hot
/public/storage
/storage/*.key
/storage/app/public
/storage/framework/cache/data
/storage/logs/*.log
/storage/framework/sessions/*
/storage/framework/views/*
/.env
.phpunit.result.cache
Homestead.json
Homestead.yaml
/nova/vendor
.env.backup
.env.local
.env.development
.env.testing
.env.staging
.env.production
# Ignora o IDE (se estiver usando)
.idea
.vscode
# Ignora arquivos de sistema
.DS_Store
Thumbs.db

@ -0,0 +1,137 @@
<p align="center"><a href="https://ae3tecnologia.com.br/" target="_blank"><img src="./resources/images/ae3.svg" width="200" alt="A&3 Logo"></a></p>
## Ae3 Auth
Esta lib padroniza o processo de autenticação e gerência de senhas utilizados na Ae3
### Requisitos
- PHP >= 8.1
- Laravel >= 10.*
- Composer >= v2
### Como configurar o projeto?
1) Adicione este repositório à lista de repositórios do composer em seu projeto laravel.
```json
{
"repositories": [
{
"type": "git",
"url": ""
}
]
}
```
2) Execute o comando a seguir para baixar esta lib ao vendor do seu projeto.
```
composer require pablo/ae3auth
```
3) Configure as variáveis abaixo no .env do seu projeto.
```
USERS_TABLE="Nome da tabela de usuários | users"
MIN_PASSWORD_LENGTH="Tamanho mínimo da senha | 8"
PASSWORD_HISTORY_TABLE="Nome da tabela de senhas a serem mantidas na base de dados | password_histories"
MAX_STORE_PASSWORDS="Quantidade máxima de senhas | 3"
USERNAME_COLUMN="Nome da coluna de usuário | username"
FORCE_CHANGE_COLUMN_NAME="Nome da coluna de alteração | force_change_password"
EXPIRES_PASSWORD_COLUMN_NAME="Nome da coluna de expiração | password_expires_at"
USER_MODEL="Modelo de usuário | App\\Models\\User"
PASSWORD_COLUMN="Nome da coluna de senha | password"
```
4) Execute o comando abaixo para criar a tabela de usuários e a tabela de senhas.
```
php artisan ae3auth:publish
```
5) Execute o comando abaixo para criar as tabelas de usuários e senhas.
```
php artisan migrate
```
6) Validação de senhas
Para validar a nova senha do usuário, no FormRequest, adicione a seguinte regra:
```php
use Pablo\Ae3auth\app\Rules\CheckUsedPasswordRule;
public function rules(): array
{
return [
'<campo_username' => '<rules>',
'password' => [
Password::defaults(),
new CheckUsedPasswordRule()
],
];
}
```
7) Invalidando senhas expiradas
Para invalidar as senhas expiradas, execute o comando abaixo:
```
php artisan ae3auth:invalidate-expired-passwords
```
Ou adicione a chamada para o comando no arquivo de schedule do seu projeto para ser executado pelo cron do sistema.
Versão 10.*:
Adicione ao arquivo ```app\Console\Kernel.php```:
``` php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
...
$schedule->command('ae3auth:invalidate-expired-passwords')->daily();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
```
Versão >= 11.*:
Adicione ao arquivo ```routes/console.php```:
``` php
...
use \Illuminate\Support\Facades\Schedule;
...
Schedule::call('ae3auth:invalidate-expired-passwords')->daily();
```

@ -0,0 +1,32 @@
{
"name": "pablo/ae3auth",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Pablo\\Ae3auth\\": "src/"
}
},
"authors": [
{
"name": "Pablo",
"email": "pablomiranda304@gmail.com"
}
],
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=8.1",
"laravel/framework": ">=10.0.0",
"laravel/sanctum": "^4.0",
"imanghafoori/laravel-smart-facades": "^1.0"
},
"extra": {
"laravel": {
"providers": [
"Pablo\\Ae3auth\\app\\Providers\\Ae3AuthServiceProvider",
"Pablo\\Ae3auth\\app\\Providers\\Ae3PasswordDefaultsServiceProvider"
]
}
}
}

5543
composer.lock generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,9 @@
<svg width="303" height="165" viewBox="0 0 303 165" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="167.946" cy="103" rx="51.5365" ry="52.8718" fill="white"/>
<path d="M113.625 128.354C108.48 116.779 106.978 103.848 109.328 91.357C111.678 78.8662 117.762 67.4368 126.736 58.6576C126.957 58.5056 127.112 58.2711 127.168 58.0038C127.223 57.7365 127.175 57.4576 127.033 57.2263C118.721 38.4153 110.429 19.5934 102.155 0.760747C102.086 0.521544 101.936 0.315138 101.733 0.177761C101.53 0.0403838 101.286 -0.0191844 101.044 0.0095128C91.02 0.0354174 80.9957 0.0354174 70.9715 0.0095128C70.707 -0.0254498 70.4391 0.0366266 70.215 0.184767C69.9909 0.332907 69.8251 0.557569 69.7468 0.819032C46.7146 53.3191 23.6761 105.817 0.63125 158.313C0.488253 158.752 0.274912 159.163 0 159.53L0 159.686C0.0735163 159.679 0.147421 159.679 0.220938 159.686C13.0479 159.686 25.8834 159.686 38.7272 159.686C38.9562 159.715 39.188 159.659 39.3796 159.527C39.5712 159.395 39.7094 159.196 39.7688 158.967C44.0423 148.747 48.2654 138.502 52.5579 128.283C63.5669 102.063 74.5338 75.8215 85.4586 49.5586C85.5533 49.3319 85.5723 49.047 85.8563 48.911L105.861 96.5042H104.882C95.3882 96.5042 85.8963 96.5042 76.4065 96.5042C76.1664 96.4677 75.9215 96.5218 75.7172 96.6563C75.5129 96.7909 75.3631 96.9968 75.2955 97.236C71.0072 107.542 66.7063 117.863 62.3928 128.199C62.0329 129.06 62.033 129.06 62.9672 129.06H113.84C113.851 128.989 113.851 128.917 113.84 128.846C113.77 128.684 113.694 128.516 113.625 128.354Z" fill="white"/>
<path d="M302.369 102.897C300.997 93.0843 296.474 84.0208 289.516 77.1417C283.759 71.3844 276.847 67.6801 269.209 65.2969C267.997 64.9212 266.779 64.591 265.472 64.2153H265.44L265.472 64.183L284.151 41.4322C283.924 41.4322 283.829 41.4322 283.734 41.4322C269.746 41.4322 255.759 41.4322 241.775 41.4322C241.59 41.4297 241.408 41.4746 241.245 41.5628C241.082 41.6511 240.943 41.7798 240.841 41.9374C234.377 49.8188 227.957 57.7392 221.404 65.543C220.022 67.2008 219.208 68.781 219.479 70.9959C219.527 71.759 219.727 72.5039 220.066 73.1848C223.487 79.404 225.788 86.2046 226.858 93.2609C226.985 94.1093 227.262 94.2712 228.026 94.2647C231.587 94.2215 235.147 94.2215 238.707 94.2647C242.919 94.2055 247.123 94.6445 251.237 95.5729C254.624 96.3194 257.792 97.8723 260.485 100.106C265.901 104.788 265.914 113.182 263.9 117.89C262.309 121.613 259.444 124.023 256.01 125.804C251.856 127.947 247.374 128.783 242.791 129.042C236.307 129.46 229.798 128.895 223.475 127.364C222.844 127.209 222.629 127.364 222.37 127.928C217.433 139.254 209.245 148.766 198.9 155.192C198.61 155.313 198.355 155.509 198.162 155.762C199.614 156.345 201.034 156.941 202.473 157.478C213.277 161.504 224.642 163.717 236.132 164.032H242.962C246.92 163.89 250.867 163.52 254.785 162.925C263.323 161.711 271.551 158.81 279.012 154.383C287.553 149.202 294.162 142.195 298.385 132.94C301.289 126.525 302.86 119.56 303 112.489V110.002C302.922 107.623 302.711 105.251 302.369 102.897Z" fill="white"/>
<path d="M126.742 33.2462C126.82 33.5182 126.99 33.7527 127.222 33.9072C127.453 34.0617 127.731 34.1258 128.005 34.0881C179.258 34.0881 230.507 34.0881 281.752 34.0881C284.353 34.0881 286.954 34.0881 289.555 34.0881C289.75 34.1049 289.947 34.0703 290.126 33.9876C290.304 33.9049 290.46 33.7768 290.577 33.6154C292.496 31.2451 294.432 28.8899 296.385 26.5499C296.73 26.1473 296.909 25.6222 296.883 25.0863C296.883 17.0688 296.883 9.04915 296.883 1.02736C296.883 -0.0735891 297.022 0.0365054 295.918 0.0365054H113.309C112.312 0.0365054 112.312 0.0365055 112.729 0.994976C117.408 11.7411 122.08 22.4915 126.742 33.2462Z" fill="white"/>
<path d="M219.465 101.711C219.218 91.3079 215.984 81.2108 210.168 72.6849C204.352 64.159 196.213 57.5836 186.77 53.7823C177.328 49.981 167.002 49.123 157.086 51.3157C147.17 53.5085 138.106 58.6544 131.028 66.1089C123.951 73.5634 119.175 82.9949 117.299 93.2218C115.423 103.449 116.53 114.016 120.483 123.6C124.435 133.184 131.056 141.358 139.516 147.099C147.977 152.84 157.9 155.891 168.044 155.871C174.913 155.873 181.713 154.463 188.042 151.724C194.372 148.985 200.102 144.973 204.895 139.924C209.688 134.876 213.447 128.894 215.949 122.33C218.452 115.767 219.647 108.756 219.465 101.711ZM203.45 88.2861C196.376 96.3381 189.289 104.381 182.19 112.416C181.679 112.993 181.899 113.232 182.31 113.627C188.201 119.404 194.093 125.185 199.985 130.97C200.288 131.275 200.894 131.547 200.673 132.052C200.515 132.421 199.941 132.201 199.555 132.201C196.879 132.201 194.209 132.201 191.532 132.201V132.305C188.73 132.305 185.927 132.305 183.124 132.305C182.938 132.315 182.752 132.287 182.578 132.221C182.403 132.155 182.243 132.054 182.108 131.922C179.412 129.39 176.692 126.884 174.009 124.332C173.58 123.931 173.346 123.963 172.986 124.365C171.278 126.415 169.3 128.211 167.109 129.701C160.62 133.807 153.752 134.785 146.669 131.644C141.039 129.164 138.16 124.481 137.725 118.251C137.472 114.014 138.473 109.797 140.597 106.154C140.756 105.815 141.013 105.536 141.332 105.353C141.652 105.169 142.019 105.092 142.383 105.131C145.91 105.251 149.443 105.292 152.982 105.254C153.493 105.254 154.244 105.474 154.44 105.008C154.636 104.541 153.891 104.166 153.518 103.796C151.318 101.775 149.246 99.6117 147.313 97.3203C144.889 94.2506 142.939 90.9284 142.263 86.9585C141.001 79.3555 144.321 72.2706 151.101 68.9483C157.88 65.626 164.742 65.7102 170.966 70.5026C175.467 73.9544 177.594 78.7467 177.209 84.5623C176.974 87.3692 175.867 90.0247 174.053 92.1394C173.902 92.3294 173.708 92.4792 173.488 92.5761C173.268 92.6731 173.029 92.7143 172.791 92.6963C169.634 92.6963 166.528 92.6963 163.397 92.6963H162.337C161.87 92.6963 161.889 92.9101 162.11 93.208C162.23 93.3757 162.363 93.5337 162.507 93.6807C165.664 96.772 168.82 99.8633 171.976 102.955C172.355 103.33 172.557 103.324 172.91 102.909C177.285 97.8643 181.685 92.8388 186.047 87.7874C186.258 87.5179 186.528 87.3027 186.835 87.1588C187.142 87.0149 187.477 86.9463 187.814 86.9585H202.731H202.882C203.255 86.9973 203.734 86.9585 203.917 87.2888C204.101 87.619 203.69 88.0141 203.45 88.2861Z" fill="#0B78B8"/>
<path d="M158.602 105.403C157.207 105.451 155.853 105.9 154.694 106.699C153.726 107.321 152.965 108.231 152.514 109.309C152.063 110.386 151.943 111.579 152.169 112.728C152.921 116.283 156.197 118.058 159.656 116.724C161.14 116.141 162.427 115.128 163.361 113.809C164.586 112.145 166.057 110.662 167.414 109.101L170.709 105.319C166.511 105.157 162.553 105.287 158.602 105.403Z" fill="#0B78B8"/>
<path d="M159.814 90.9617C160.123 91.2467 160.356 91.2078 160.628 90.8905C161.209 90.2105 161.852 89.5952 162.421 88.8893C163.538 87.7096 164.192 86.1486 164.258 84.505C164.253 84.0906 164.205 83.678 164.112 83.2745C163.967 82.7438 163.721 82.2478 163.388 81.8149C163.055 81.3819 162.642 81.0207 162.173 80.7517C161.704 80.4828 161.188 80.3115 160.654 80.2477C160.12 80.1838 159.579 80.2287 159.062 80.3797C158.009 80.6994 157.123 81.4346 156.597 82.4241C156.072 83.4136 155.95 84.5765 156.26 85.6577C156.936 87.7329 158.167 89.5709 159.814 90.9617Z" fill="#0B78B8"/>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

@ -0,0 +1,32 @@
<?php
namespace Pablo\Ae3auth\app\Console\Commands;
use Illuminate\Console\Command;
class InvalidateExpiredPasswordsCommand extends Command
{
protected $signature = 'ae3auth:invalidate-expired-passwords';
protected $description = 'Invalidate passwords when reach the expiration date';
public function handle(): void
{
try {
$userModel = config('ae3auth-config.user.user_model');
$users = $userModel::whereDate(config('ae3auth-config.user.expires_password_column_name'), '<=', now())->get();
$forceChangePasswordColumnName = config('ae3auth-config.user.force_change_column_name');
\DB::beginTransaction();
$users->each(function ($user) use ($forceChangePasswordColumnName) {
tap($user, fn($model) => $model->update([
$forceChangePasswordColumnName => true
]));
});
\DB::commit();
$this->info(__('expirated_passwords_invalidated'));
} catch (\Exception $exception) {
\DB::rollBack();
$this->error(__('expirated_passwords_invalidated_error'));
}
}
}

@ -0,0 +1,19 @@
<?php
namespace Pablo\Ae3auth\app\Console\Commands;
use Illuminate\Console\Command;
class PublishCommand extends Command
{
protected $signature = 'ae3auth:publish';
protected $description = 'Publish files';
public function handle(): void
{
$this->call('vendor:publish', ['--tag' => 'ae3auth-models']);
$this->call('vendor:publish', ['--tag' => 'ae3auth-migrations']);
$this->call('vendor:publish', ['--tag' => 'ae3auth-config']);
}
}

@ -0,0 +1,14 @@
<?php
namespace Pablo\Ae3auth\app\Facades;
use Imanghafoori\SmartFacades\Facade;
/**
* @method static inHistory(int|string $userId, string $password): bool
* @method static logNewPassword(int|string $userId, string $password): bool
* @method static logPassword($user): bool
*/
class PasswordHistoryManager extends Facade
{
}

@ -0,0 +1,22 @@
<?php
namespace Pablo\Ae3auth\app\Models;
use Illuminate\Database\Eloquent\Model;
class PasswordHistory extends Model
{
/**
* @var string[]
*/
protected $fillable = [
'user_id',
'password',
'last_used_at'
];
public function setTable($table)
{
return config('ae3auth-config.password_history_table');
}
}

@ -0,0 +1,26 @@
<?php
namespace Pablo\Ae3auth\app\Observers;
use Pablo\Ae3auth\app\Facades\PasswordHistoryManager;
class UserObserver
{
/**
* @param $user
* @return void
*/
public function updating($user): void
{
PasswordHistoryManager::logPassword($user);
}
/**
* @param $user
* @return void
*/
public function created($user): void
{
PasswordHistoryManager::logNewPassword($user->id, $user->password);
}
}

@ -0,0 +1,67 @@
<?php
namespace Pablo\Ae3auth\app\Providers;
use Illuminate\Support\ServiceProvider;
use Pablo\Ae3auth\app\Console\Commands\InvalidateExpiredPasswordsCommand;
use Pablo\Ae3auth\app\Console\Commands\PublishCommand;
use Pablo\Ae3auth\app\Facades\PasswordHistoryManager;
use Pablo\Ae3auth\app\Observers\UserObserver;
use Pablo\Ae3auth\app\Services\PasswordHistoryService;
class Ae3AuthServiceProvider extends ServiceProvider
{
/**
* @return void
*/
public function register(): void
{
PasswordHistoryManager::shouldProxyTo(PasswordHistoryService::class);
$this->registerCommands();
$this->mergeConfig();
}
/**
* @return void
*/
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__ . '/../../config/ae3auth.php' => config_path('ae3auth.php')
], 'ae3auth-config');
$this->publishes([
__DIR__ . '/../../database/migrations' => database_path('migrations')
], 'ae3auth-migrations');
$this->publishes([
__DIR__ . '/../Models/PasswordHistory.php' => app_path('Models\\PasswordHistory.php')
], 'ae3auth-models');
}
$userModel = config('ae3auth-config.user.user_model');
$userModel::observe(UserObserver::class);
}
private function mergeConfig(): void
{
$this->mergeConfigFrom(
__DIR__ . '/../../config/ae3auth.php',
'ae3auth-config'
);
}
/**
* @return void
*/
protected function registerCommands(): void
{
if ($this->app->runningInConsole()) {
$this->commands([
PublishCommand::class,
InvalidateExpiredPasswordsCommand::class
]);
}
}
}

@ -0,0 +1,25 @@
<?php
namespace Pablo\Ae3auth\app\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password;
class Ae3PasswordDefaultsServiceProvider extends ServiceProvider
{
public function register(): void
{
}
public function boot(): void
{
Password::defaults(function () {
return Password::min(config('ae3auth-config.min_password_length'))
->mixedCase()
->numbers()
->symbols()
->uncompromised();
});
}
}

@ -0,0 +1,47 @@
<?php
namespace Pablo\Ae3auth\app\Repositories;
use Illuminate\Support\Facades\Hash;
use Pablo\Ae3auth\app\Models\PasswordHistory;
class PasswordHistoryRepository
{
/**
* @param int|string $userId
* @return mixed
*/
public function passwords(int|string $userId): mixed
{
return PasswordHistory::where('user_id', $userId)->get();
}
/**
* @param string $password
* @param int|string $userId
* @return void
* @throws \Throwable
*/
public function storeNewPassword(string $password, int|string $userId): void
{
PasswordHistory::create([
'password' => $password,
'user_id' => $userId,
'last_used_at' => now()
]);
}
/**
* @param $userId
* @return mixed
*/
public function oldestPassword($userId): mixed
{
return PasswordHistory::where('user_id', $userId)->orderBy('last_used_at', 'asc')->first();
}
public function destroy($id): void
{
PasswordHistory::destroy($id);
}
}

@ -0,0 +1,34 @@
<?php
namespace Pablo\Ae3auth\app\Rules;
use Closure;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Pablo\Ae3auth\app\Facades\PasswordHistoryManager;
class CheckUsedPasswordRule implements ValidationRule, DataAwareRule
{
/**
* @var array
*/
private array $data = [];
public function validate(string $attribute, $value, Closure $fail): void
{
$usernameColumn = config('ae3auth-config.user.username_column');
$userModel = config('ae3auth-config.user.user_model');
if (!$user = auth()->user()) {
$user = $userModel::firstWhere($usernameColumn, $this->data[$usernameColumn]);
$user ?: $fail(__('failed'));
}
if (!PasswordHistoryManager::inHistory($user->id, $value)) {
$fail(__('auth.password_used'));
}
}
public function setData(array $data)
{
$this->data = $data;
}
}

@ -0,0 +1,32 @@
<?php
namespace Pablo\Ae3auth\app\Services\Contracts;
interface PasswordHistoryServiceContract
{
/**
* @param int|string $userId
* @param string $password
* @return bool
*/
public function inHistory(int|string $userId, string $password): bool;
/**
* @param $user
* @return void
*/
public function logPassword($user): void;
/**
* @param int|string $userId
* @param string $password
* @return bool
*/
public function logNewPassword(int|string $userId, string $password): void;
/**
* @param $userId
* @return void
*/
public function removeOldestPassword($userId): void;
}

@ -0,0 +1,68 @@
<?php
namespace Pablo\Ae3auth\app\Services;
use Illuminate\Support\Facades\Hash;
use Pablo\Ae3auth\app\Repositories\PasswordHistoryRepository;
use Pablo\Ae3auth\app\Services\Contracts\PasswordHistoryServiceContract;
class PasswordHistoryService implements Contracts\PasswordHistoryServiceContract
{
public function __construct(
private readonly PasswordHistoryRepository $passwordHistoryRepository
)
{
}
/**
* @inheritDoc
*/
public function inHistory(int|string $userId, string $password): bool
{
$passwords = $this->passwordHistoryRepository->passwords($userId);
foreach ($passwords as $history) {
if (Hash::check($password, $history->password)) {
return false;
}
}
return true;
}
/**
* @param $user
* @return void
*/
public function logPassword($user): void
{
$passwords = $this->passwordHistoryRepository->passwords($user->id);
if (count($passwords) >= config('ae3auth-config.max_stored_passwords')) {
$this->removeOldestPassword($user->id);
}
$passwordCol = config('ae3auth-config.user.password_column');
if ($user->$passwordCol && $user->isDirty($passwordCol)) {
$this->logNewPassword($user->id, $user->$passwordCol);
}
}
/**
* @inheritDoc
*/
public function logNewPassword(int|string $userId, string $password): void
{
$this->passwordHistoryRepository->storeNewPassword($password, $userId);
}
/**
* @param $userId
* @return void
*/
public function removeOldestPassword($userId): void
{
$oldest = $this->passwordHistoryRepository->oldestPassword($userId);
if ($oldest) {
$this->passwordHistoryRepository->destroy($oldest->id);
}
}
}

@ -0,0 +1,25 @@
<?php
namespace Pablo\Ae3auth\app\Traits;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use Symfony\Component\HttpFoundation\Response;
trait ValidationErrorResponse
{
/**
* @param Validator $validator
* @param string|null $message
* @return mixed
*/
public function throwAndReturnJsonResponse(Validator $validator, ?string $message = null): mixed
{
throw new HttpResponseException(
response: response()->json([
'message' => $message ?? __('messages.errors.unprocessable_entity'),
'errors' => $validator->errors()
], status: Response::HTTP_UNPROCESSABLE_ENTITY)
);
}
}

@ -0,0 +1,34 @@
<?php
return [
/**
* Where users are stored
*/
'users_table' => env('USERS_TABLE', 'users'),
/**
* Minimum length of password
*/
'min_password_length' => intval(env('MIN_PASSWORD_LENGTH', 8)),
/**
* Table to store used passwords
*/
'password_history_table' => \Illuminate\Support\Str::plural(env('PASSWORD_HISTORY_TABLE', 'password_history')),
/**
* Maximum of passwords stored in history
*/
'max_stored_passwords' => intval(env('MAX_STORE_PASSWORDS', 3)),
/**
* User table definitions
*/
'user' => [
'username_column' => env('USERNAME_COLUMN', 'username'),
'force_change_column_name' => env('FORCE_CHANGE_COLUMN_NAME', 'force_change_password'),
'expires_password_column_name' => env('EXPIRES_PASSWORD_COLUMN_NAME', 'password_expires_at'),
'user_model' => env('USER_MODEL', 'App\\Models\\User'),
'password_column' => env('PASSWORD_COLUMN', 'password'),
]
];

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
private string $tableName;
private string $columnName;
public function __construct()
{
$this->tableName = config('ae3auth-config.users_table');
$this->columnName = config('ae3auth-config.user.force_change_column_name');
}
public function up(): void
{
if (!Schema::hasColumn($this->tableName, $this->columnName)) {
Schema::table($this->tableName, function (Blueprint $table) {
$table->boolean($this->columnName)->default(false);
});
}
}
public function down(): void
{
Schema::table($this->tableName, function (Blueprint $table) {
$table->dropColumn($this->columnName);
});
}
};

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
private string $tableName;
private string $columnName;
public function __construct()
{
$this->tableName = config('ae3auth-config.users_table');
$this->columnName = config('ae3auth-config.user.expires_password_column_name');
}
public function up(): void
{
if (!Schema::hasColumn($this->tableName, $this->columnName)) {
Schema::table($this->tableName, function (Blueprint $table) {
$table->dateTime($this->columnName)->nullable()->default(null);
});
}
}
public function down(): void
{
Schema::table($this->tableName, function (Blueprint $table) {
$table->dropColumn($this->columnName);
});
}
};

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
private string $tableName;
private string $usersTable;
public function __construct()
{
$this->tableName = config('ae3auth-config.password_history_table');
$this->usersTable = config('ae3auth-config.users_table');
}
public function up(): void
{
if (!Schema::hasTable($this->tableName)) {
Schema::create($this->tableName, function (Blueprint $table) {
$table->id();
$table->string('password');
$table->foreignId('user_id')->constrained($this->usersTable)->cascadeOnDelete();
$table->dateTime('last_used_at')->nullable()->default(null);
$table->unique(['user_id', 'password']);
$table->timestamps();
});
}
}
public function down(): void
{
Schema::dropIfExists($this->tableName);
}
};
Loading…
Cancel
Save