feat: implement user registration functionality with validation and response handling
This commit is contained in:
27
app/Domains/Auth/Controllers/RegisterController.php
Normal file
27
app/Domains/Auth/Controllers/RegisterController.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Auth\Controllers;
|
||||||
|
|
||||||
|
use App\Domains\Auth\Requests\RegisterUserRequest;
|
||||||
|
use App\Domains\Auth\Resources\UserResource;
|
||||||
|
use App\Domains\Auth\Services\RegisterUserService;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class RegisterController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected RegisterUserService $registerUserService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(RegisterUserRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$user = $this->registerUserService->register($request->validated());
|
||||||
|
|
||||||
|
return UserResource::make($user)
|
||||||
|
->additional(['message' => 'Usuario registrado correctamente.'])
|
||||||
|
->response()
|
||||||
|
->setStatusCode(201);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Domains\Auth\Models;
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
|
||||||
use Database\Factories\UserFactory;
|
use Database\Factories\UserFactory;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
||||||
@@ -10,16 +9,19 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
#[Fillable(['name', 'email', 'password'])]
|
#[Fillable(['nombre_apellido', 'email', 'password'])]
|
||||||
#[Hidden(['password', 'remember_token'])]
|
#[Hidden(['password', 'remember_token'])]
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
/** @use HasFactory<UserFactory> */
|
/** @use HasFactory<UserFactory> */
|
||||||
use HasFactory, Notifiable;
|
use HasFactory, Notifiable;
|
||||||
|
|
||||||
|
protected static function newFactory(): UserFactory
|
||||||
|
{
|
||||||
|
return UserFactory::new();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the attributes that should be cast.
|
|
||||||
*
|
|
||||||
* @return array<string, string>
|
* @return array<string, string>
|
||||||
*/
|
*/
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
26
app/Domains/Auth/Requests/RegisterUserRequest.php
Normal file
26
app/Domains/Auth/Requests/RegisterUserRequest.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Auth\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class RegisterUserRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nombre_apellido' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users', 'email')],
|
||||||
|
'password' => ['required', 'string', 'confirmed'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/Domains/Auth/Resources/UserResource.php
Normal file
24
app/Domains/Auth/Resources/UserResource.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Auth\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mixin \App\Domains\Auth\Models\User
|
||||||
|
*/
|
||||||
|
class UserResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'nombre_apellido' => $this->nombre_apellido,
|
||||||
|
'email' => $this->email,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Domains/Auth/Services/RegisterUserService.php
Normal file
20
app/Domains/Auth/Services/RegisterUserService.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Auth\Services;
|
||||||
|
|
||||||
|
use App\Domains\Auth\Models\User;
|
||||||
|
|
||||||
|
class RegisterUserService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array{nombre_apellido: string, email: string, password: string} $data
|
||||||
|
*/
|
||||||
|
public function register(array $data): User
|
||||||
|
{
|
||||||
|
return User::query()->create([
|
||||||
|
'nombre_apellido' => $data['nombre_apellido'],
|
||||||
|
'email' => $data['email'],
|
||||||
|
'password' => $data['password'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
app/Domains/Auth/routes/api.php
Normal file
6
app/Domains/Auth/routes/api.php
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Domains\Auth\Controllers\RegisterController;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::post('register', RegisterController::class);
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Domains\Cart\Models;
|
namespace App\Domains\Cart\Models;
|
||||||
|
|
||||||
|
use App\Domains\Auth\Models\User;
|
||||||
use App\Domains\Catalog\Models\ProductVariant;
|
use App\Domains\Catalog\Models\ProductVariant;
|
||||||
use App\Domains\Tenant\Models\Tenant;
|
use App\Domains\Tenant\Models\Tenant;
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
namespace App\Domains\Cart\Services;
|
namespace App\Domains\Cart\Services;
|
||||||
|
|
||||||
use App\Domains\Cart\Models\Cart;
|
use App\Domains\Cart\Models\Cart;
|
||||||
|
use App\Domains\Auth\Models\User;
|
||||||
use App\Domains\Tenant\Models\Tenant;
|
use App\Domains\Tenant\Models\Tenant;
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Symfony\Component\HttpFoundation\Cookie;
|
use Symfony\Component\HttpFoundation\Cookie;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Domains\Purchase\Models;
|
namespace App\Domains\Purchase\Models;
|
||||||
|
|
||||||
|
use App\Domains\Auth\Models\User;
|
||||||
use App\Domains\Tenant\Models\Tenant;
|
use App\Domains\Tenant\Models\Tenant;
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Domains\Auth\Models\User;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Domains\Auth\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
@@ -12,6 +12,8 @@ use Illuminate\Support\Str;
|
|||||||
*/
|
*/
|
||||||
class UserFactory extends Factory
|
class UserFactory extends Factory
|
||||||
{
|
{
|
||||||
|
protected $model = User::class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current password being used by the factory.
|
* The current password being used by the factory.
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +27,7 @@ class UserFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => fake()->name(),
|
'nombre_apellido' => fake()->name(),
|
||||||
'email' => fake()->unique()->safeEmail(),
|
'email' => fake()->unique()->safeEmail(),
|
||||||
'email_verified_at' => now(),
|
'email_verified_at' => now(),
|
||||||
'password' => static::$password ??= Hash::make('password'),
|
'password' => static::$password ??= Hash::make('password'),
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('name', 'nombre_apellido');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('nombre_apellido', 'name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Domains\Auth\Models\User;
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class DatabaseSeeder extends Seeder
|
|||||||
// User::factory(10)->create();
|
// User::factory(10)->create();
|
||||||
|
|
||||||
User::factory()->create([
|
User::factory()->create([
|
||||||
'name' => 'Test User',
|
'nombre_apellido' => 'Test User',
|
||||||
'email' => 'test@example.com',
|
'email' => 'test@example.com',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ Route::get('/user', function (Request $request) {
|
|||||||
return $request->user();
|
return $request->user();
|
||||||
})->middleware('auth:sanctum');
|
})->middleware('auth:sanctum');
|
||||||
|
|
||||||
|
require __DIR__.'/../app/Domains/Auth/routes/api.php';
|
||||||
require __DIR__.'/../app/Domains/Catalog/routes/api.php';
|
require __DIR__.'/../app/Domains/Catalog/routes/api.php';
|
||||||
require __DIR__.'/../app/Domains/Cart/routes/api.php';
|
require __DIR__.'/../app/Domains/Cart/routes/api.php';
|
||||||
require __DIR__.'/../app/Domains/StorageTest/routes/api.php';
|
require __DIR__.'/../app/Domains/StorageTest/routes/api.php';
|
||||||
|
|||||||
58
tests/Feature/Auth/RegisterControllerTest.php
Normal file
58
tests/Feature/Auth/RegisterControllerTest.php
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Auth;
|
||||||
|
|
||||||
|
use App\Domains\Auth\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class RegisterControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
public function test_it_registers_a_user(): void
|
||||||
|
{
|
||||||
|
$response = $this->postJson('/api/register', [
|
||||||
|
'nombre_apellido' => 'Ada Lovelace',
|
||||||
|
'email' => 'ada@example.com',
|
||||||
|
'password' => 'secret123',
|
||||||
|
'password_confirmation' => 'secret123',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertCreated()
|
||||||
|
->assertJsonPath('message', 'Usuario registrado correctamente.')
|
||||||
|
->assertJsonPath('data.nombre_apellido', 'Ada Lovelace')
|
||||||
|
->assertJsonPath('data.email', 'ada@example.com');
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('users', [
|
||||||
|
'nombre_apellido' => 'Ada Lovelace',
|
||||||
|
'email' => 'ada@example.com',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::query()->where('email', 'ada@example.com')->firstOrFail();
|
||||||
|
|
||||||
|
$this->assertNotSame('secret123', $user->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_validates_required_fields_and_unique_email(): void
|
||||||
|
{
|
||||||
|
User::factory()->create([
|
||||||
|
'nombre_apellido' => 'Existing User',
|
||||||
|
'email' => 'existing@example.com',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->postJson('/api/register', [
|
||||||
|
'nombre_apellido' => '',
|
||||||
|
'email' => 'existing@example.com',
|
||||||
|
'password' => 'secret123',
|
||||||
|
'password_confirmation' => 'different-secret',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertUnprocessable()->assertJsonValidationErrors([
|
||||||
|
'nombre_apellido',
|
||||||
|
'email',
|
||||||
|
'password',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace Tests\Feature\Cart;
|
namespace Tests\Feature\Cart;
|
||||||
|
|
||||||
|
use App\Domains\Auth\Models\User;
|
||||||
use App\Domains\Catalog\Models\Product;
|
use App\Domains\Catalog\Models\Product;
|
||||||
use App\Domains\Catalog\Models\Attribute;
|
use App\Domains\Catalog\Models\Attribute;
|
||||||
use App\Domains\Catalog\Models\ProductVariant;
|
use App\Domains\Catalog\Models\ProductVariant;
|
||||||
use App\Domains\Catalog\Models\ProductAttribute;
|
use App\Domains\Catalog\Models\ProductAttribute;
|
||||||
use App\Domains\Catalog\Models\ProductVariantDefinition;
|
use App\Domains\Catalog\Models\ProductVariantDefinition;
|
||||||
use App\Domains\Tenant\Models\Tenant;
|
use App\Domains\Tenant\Models\Tenant;
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user