diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cfd2d9..4f2ff51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: stability: [prefer-stable] php: [8.2, 8.3, 8.4] - laravel: [11] + laravel: [12] name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} diff --git a/composer.json b/composer.json index 6cc22a0..5d0da28 100644 --- a/composer.json +++ b/composer.json @@ -11,20 +11,20 @@ ], "require": { "php": "^8.2", - "api-ecosystem-for-laravel/dingo-api": "^4.4.1", - "php-open-source-saver/jwt-auth": "^2.7", - "illuminate/support": "^11.0", + "api-ecosystem-for-laravel/dingo-api": "^4.6", + "php-open-source-saver/jwt-auth": "^2.8", + "illuminate/support": "^12.0", "ramsey/uuid": "^4.7", - "nesbot/carbon": "^2.0|^3.0" + "nesbot/carbon": "^3.0" }, "require-dev": { "ext-json": "*", - "beyondcode/laravel-dump-server": "^2.0", - "fakerphp/faker": "^1.23", + "beyondcode/laravel-dump-server": "^2.1", + "fakerphp/faker": "^1.24", "mockery/mockery": "^1.6", "nunomaduro/collision": "^8.6", "phpunit/phpunit": "^11.5", - "orchestra/testbench": "^9.9" + "orchestra/testbench": "^10.3" }, "autoload": { "psr-4": { @@ -37,9 +37,10 @@ "Specialtactics\\L5Api\\Tests\\": "test/tests/", "Specialtactics\\L5Api\\Test\\Mocks\\": "test/mocks/", "App\\": "test/app/", - "Database\\": "test/database/" + "Database\\Factories\\": "test/database/factories/", + "Database\\Seeders\\": "test/database/seeders/" }, - "classmap": ["test/database/seeds/"] + "classmap": ["test/database/migrations/"] }, "extra": { "laravel": { diff --git a/readme.md b/readme.md index bf78092..809697e 100644 --- a/readme.md +++ b/readme.md @@ -12,8 +12,9 @@ Please go to [The boilerplate wiki](https://github.com/specialtactics/laravel-ap | Laravel Version | Boilerplate Version | Minimum PHP Version | Support Status | |-----------------|---------------------|---------------------|----------------| +| 12.x | 7.x.x | 8.2 | Supported | | 11.x | 6.x.x | 8.2 | Supported | -| 10.x | 5.x.x | 8.1 | Supported | +| 10.x | 5.x.x | 8.1 | Not Supported | | 9.x | 4.x.x | 8.0 | Not Supported | | 8.x | 3.x.x | 7.3 | Not Supported | | 7.x | 2.x.x | 7.2.5 | Not Supported | diff --git a/test/app/Models/User.php b/test/app/Models/User.php index 3edca8a..9a562fd 100644 --- a/test/app/Models/User.php +++ b/test/app/Models/User.php @@ -12,7 +12,6 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Support\Str; use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject; -use \Illuminate\Support\Facades\Hash; use App\Models\Role; use Database\Factories\UserFactory; @@ -43,11 +42,6 @@ class User extends BaseModel implements 'name', 'email', 'password', 'primary_role' ]; - protected $casts = [ - 'verifiable_until' => 'datetime', - 'password' => 'hashed', - ]; - /** * The attributes that should be hidden for arrays and API output */ @@ -55,6 +49,19 @@ class User extends BaseModel implements 'password', 'remember_token', 'primary_role', ]; + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + /** * Model's boot function */ @@ -62,10 +69,8 @@ public static function boot(): void { parent::boot(); - static::creating(function (User $user) { - if (is_null($user->password)) { - $user->password = Hash::make(Str::random(64)); - } + static::saving(function (User $user) { + $user->email = Str::lower($user->email); }); } diff --git a/test/database/factories/UserFactory.php b/test/database/factories/UserFactory.php new file mode 100644 index 0000000..e3921d6 --- /dev/null +++ b/test/database/factories/UserFactory.php @@ -0,0 +1,78 @@ + + */ +class UserFactory extends Factory +{ + public const DEFAULT_PASSWORD = 'secret'; + + /** + * The name of the factory's corresponding model. + * + * @var string + */ + protected $model = User::class; + + protected static ?Collection $allRoles = null; + + /** + * Retrieve all roles + */ + public static function getAllRoles(): Collection + { + if (is_null(static::$allRoles)) { + static::$allRoles = Role::all(); + } + + return static::$allRoles; + } + + /** + * Define the model's default state. + */ + public function definition(): array + { + return [ + 'name' => $this->faker->name(), + 'email' => microtime(true) . '_' . $this->faker->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::DEFAULT_PASSWORD, + 'remember_token' => Str::random(10), + 'active' => true, + ]; + } + + public function adminRole(): UserFactory + { + return $this->state(function (array $attributes): array { + return [ + 'primary_role' => static::getAllRoles() + ->firstWhere('name', '=', Role::ROLE_ADMIN) + ->getKey(), + ]; + }); + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): UserFactory + { + return $this->state(function (array $attributes): array { + return [ + 'email_verified_at' => null, + ]; + }); + } +} diff --git a/test/database/migrations/2018_04_30_000010_create_test_users_table.php b/test/database/migrations/2018_04_30_000010_create_test_users_table.php index 7d610a9..78a7051 100644 --- a/test/database/migrations/2018_04_30_000010_create_test_users_table.php +++ b/test/database/migrations/2018_04_30_000010_create_test_users_table.php @@ -21,9 +21,11 @@ public function up() $table->string('name'); $table->string('email')->unique(); $table->string('password'); + $table->boolean('active')->default(true); $table->uuid('primary_role')->nullable(); $table->foreign('primary_role')->references('role_id')->on('roles')->onDelete('set null'); + $table->timestamp('email_verified_at')->nullable(); $table->primary('user_id'); diff --git a/test/database/seeds/BaseSeeder.php b/test/database/seeders/BaseSeeder.php similarity index 76% rename from test/database/seeds/BaseSeeder.php rename to test/database/seeders/BaseSeeder.php index a14370f..3f5eee2 100644 --- a/test/database/seeds/BaseSeeder.php +++ b/test/database/seeders/BaseSeeder.php @@ -1,5 +1,7 @@ faker = Faker\Factory::create(); + $this->faker = \Faker\Factory::create(); $this->before(); @@ -25,7 +27,7 @@ public function run() $this->runAlways(); // Production Only - if (App::environment() == 'production') { + if (app()->environment() === 'production') { $this->runProduction(); } // Fake environments @@ -37,7 +39,7 @@ public function run() } /** - * Run fake seeds - for non production environments + * Run fake Seeders - for non production environments * * @return void */ @@ -45,7 +47,7 @@ public function runFake() { } /** - * Run seeds to be ran only on production environments + * Run Seeders to be ran only on production environments * * @return void */ @@ -53,7 +55,7 @@ public function runProduction() { } /** - * Run seeds to be ran on every environment (including production) + * Run Seeders to be ran on every environment (including production) * * @return void */ diff --git a/test/database/seeds/DatabaseSeeder.php b/test/database/seeders/DatabaseSeeder.php similarity index 85% rename from test/database/seeds/DatabaseSeeder.php rename to test/database/seeders/DatabaseSeeder.php index f0ba049..12996d5 100644 --- a/test/database/seeds/DatabaseSeeder.php +++ b/test/database/seeders/DatabaseSeeder.php @@ -1,11 +1,13 @@