From 6d616edefebd3b18250aaa5eb557e6d3dd12f40a Mon Sep 17 00:00:00 2001 From: frois Date: Sun, 15 Dec 2024 19:10:30 +0100 Subject: [PATCH 1/7] feat: add endpoints for fetching and updating user data, add validation rules --- app/Http/Controllers/AuthController.php | 24 ++++++++++- app/Http/Requests/UserUpdateRequest.php | 42 +++++++++++++++++++ app/Http/Resources/UserResource.php | 19 +++++++++ app/Models/User.php | 14 +++++++ .../0001_01_01_000000_create_users_table.php | 15 +++++++ ...12_create_personal_access_tokens_table.php | 33 --------------- routes/api.php | 8 ++++ 7 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 app/Http/Requests/UserUpdateRequest.php create mode 100644 app/Http/Resources/UserResource.php delete mode 100644 database/migrations/2024_11_14_220412_create_personal_access_tokens_table.php diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 1519d4f..1f45626 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -2,13 +2,15 @@ namespace App\Http\Controllers; +use App\Http\Requests\UserUpdateRequest; +use App\Http\Resources\UserResource; use App\Models\User; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\ValidationException; -use Log; use Symfony\Component\HttpFoundation\Response; use App\Http\Requests\LoginRequest; @@ -68,4 +70,24 @@ public function login(LoginRequest $request): JsonResponse 'message' => 'Login successful', ], Response::HTTP_OK); } + + public function user(): UserResource + { + return new UserResource(auth()->user()); + } + + public function update(UserUpdateRequest $request): JsonResponse + { + $data = $request->validated(); + $user = auth()->user(); + + try { + $user->update($data); + } + catch (Exception $e) + { + return response()->json(['message' => "Failed to update user's profile!"], Response::HTTP_INTERNAL_SERVER_ERROR); + } + return response()->json(['success' => true], Response::HTTP_OK); + } } diff --git a/app/Http/Requests/UserUpdateRequest.php b/app/Http/Requests/UserUpdateRequest.php new file mode 100644 index 0000000..2e0b563 --- /dev/null +++ b/app/Http/Requests/UserUpdateRequest.php @@ -0,0 +1,42 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', + 'last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', + 'email' => 'email|max:255', + 'phone_number' => 'string|regex:/^\+?\d{9,15}$/', + 'voivodship' => 'string|min:1|max:30', + 'city' => 'string|min:1|max:30', + 'zip_code' => 'string|regex:/^\d{2}-\d{3}$/', + 'street' => 'string|min:1|max:30', + 'house_number' => 'string|regex:/^\d+[a-zA-Z]?$/', + + 'card_first_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', + 'card_last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', + 'card_number' => 'string|regex:/^\d{16}$/', + 'card_expiry_date' => 'string|regex:/^\d{2}\/\d{2}$/', + 'card_cvv' => 'string|regex:/^\d{3,4}$/', + ]; + } +} diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php new file mode 100644 index 0000000..3b6b127 --- /dev/null +++ b/app/Http/Resources/UserResource.php @@ -0,0 +1,19 @@ + + */ + public function toArray(Request $request): array + { + return parent::toArray($request); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 0d72c93..58b2fa4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -21,8 +21,22 @@ class User extends Authenticatable */ protected $fillable = [ 'name', + 'last_name', 'email', 'password', + 'phone_number', + 'voivodship', + 'city', + 'zip_code', + 'street', + 'house_number', + + 'card_first_name', + 'card_last_name', + 'card_number', + 'card_expiry_date', + 'card_cvv', + ]; /** diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 05fb5d9..7926877 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -14,9 +14,24 @@ public function up(): void Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); + $table->string('last_name')->nullable(); $table->string('email')->unique(); + $table->string('role')->nullable(); + $table->string('phone_number')->nullable(); + $table->string('voivodship')->nullable(); + $table->string('city')->nullable(); + $table->string('zip_code')->nullable(); + $table->string('street')->nullable(); + $table->string('house_number')->nullable(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); + + $table->string('card_first_name')->nullable(); + $table->string('card_last_name')->nullable(); + $table->string('card_number')->nullable(); + $table->string('card_expiry_date')->nullable(); + $table->string('card_cvv')->nullable(); + $table->rememberToken(); $table->timestamps(); }); diff --git a/database/migrations/2024_11_14_220412_create_personal_access_tokens_table.php b/database/migrations/2024_11_14_220412_create_personal_access_tokens_table.php deleted file mode 100644 index e828ad8..0000000 --- a/database/migrations/2024_11_14_220412_create_personal_access_tokens_table.php +++ /dev/null @@ -1,33 +0,0 @@ -id(); - $table->morphs('tokenable'); - $table->string('name'); - $table->string('token', 64)->unique(); - $table->text('abilities')->nullable(); - $table->timestamp('last_used_at')->nullable(); - $table->timestamp('expires_at')->nullable(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('personal_access_tokens'); - } -}; diff --git a/routes/api.php b/routes/api.php index d535ddb..abb36e2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -6,6 +6,12 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +Route::middleware('auth:sanctum')->group(function () { + Route::controller(AuthController::class)->group(function () { + Route::get('user', 'user'); + Route::put('user', 'update'); + }); +}); Route::get('/user', function (Request $request) { return $request->user(); })->middleware('auth:sanctum'); @@ -17,3 +23,5 @@ Route::get('/google/redirect', [GoogleAuthController::class, 'redirectToGoogle']); Route::get('/google/callback', [GoogleAuthController::class, 'handleGoogleCallback']); + + From d1e7bb291c8dd7a87652600113352c7bfa03ef9f Mon Sep 17 00:00:00 2001 From: marioooo0o Date: Tue, 17 Dec 2024 22:17:04 +0000 Subject: [PATCH 2/7] PHP Linting (Pint) --- app/Http/Controllers/AuthController.php | 8 +++----- routes/api.php | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 799f10c..0b21ed0 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -2,14 +2,13 @@ namespace App\Http\Controllers; +use App\Http\Requests\LoginRequest; use App\Http\Requests\UserUpdateRequest; use App\Http\Resources\UserResource; -use App\Http\Requests\LoginRequest; use App\Models\User; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpFoundation\Response; @@ -82,11 +81,10 @@ public function update(UserUpdateRequest $request): JsonResponse try { $user->update($data); - } - catch (Exception $e) - { + } catch (Exception $e) { return response()->json(['message' => "Failed to update user's profile!"], Response::HTTP_INTERNAL_SERVER_ERROR); } + return response()->json(['success' => true], Response::HTTP_OK); } } diff --git a/routes/api.php b/routes/api.php index 88e2cc4..bc17238 100644 --- a/routes/api.php +++ b/routes/api.php @@ -23,5 +23,3 @@ Route::get('/google/redirect', [GoogleAuthController::class, 'redirectToGoogle']); Route::get('/google/callback', [GoogleAuthController::class, 'handleGoogleCallback']); - - From be9cd8e9fd9c4f9bd1580829e3b32139b1245a4f Mon Sep 17 00:00:00 2001 From: frois Date: Wed, 18 Dec 2024 13:02:40 +0100 Subject: [PATCH 3/7] refactor: - change structures in controllers - card informations move to seperated table - ensure that data is properly stored, returned and encrypted --- app/Http/Controllers/AuthController.php | 34 +++++++++--------- app/Http/Controllers/CreditCardController.php | 24 +++++++++++++ app/Http/Requests/UpdateCreditCardRequest.php | 30 ++++++++++++++++ ...pdateRequest.php => UpdateUserRequest.php} | 15 ++++---- app/Http/Resources/CreditCardResource.php | 36 +++++++++++++++++++ app/Models/CreditCard.php | 35 ++++++++++++++++++ app/Models/User.php | 12 +++---- app/Services/CreditCardService.php | 20 +++++++++++ app/Services/UserService.php | 19 ++++++++++ database/factories/CreditCardFactory.php | 29 +++++++++++++++ .../0001_01_01_000000_create_users_table.php | 6 ---- ...12_18_090401_create_credit_cards_table.php | 33 +++++++++++++++++ routes/api.php | 18 ++++++++-- 13 files changed, 271 insertions(+), 40 deletions(-) create mode 100644 app/Http/Controllers/CreditCardController.php create mode 100644 app/Http/Requests/UpdateCreditCardRequest.php rename app/Http/Requests/{UserUpdateRequest.php => UpdateUserRequest.php} (69%) create mode 100644 app/Http/Resources/CreditCardResource.php create mode 100644 app/Models/CreditCard.php create mode 100644 app/Services/CreditCardService.php create mode 100644 app/Services/UserService.php create mode 100644 database/factories/CreditCardFactory.php create mode 100644 database/migrations/2024_12_18_090401_create_credit_cards_table.php diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 0b21ed0..8eae8f2 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -2,19 +2,28 @@ namespace App\Http\Controllers; -use App\Http\Requests\LoginRequest; -use App\Http\Requests\UserUpdateRequest; +use App\Http\Requests\UpdateCreditCardRequest; +use App\Http\Requests\UpdateUserRequest; use App\Http\Resources\UserResource; use App\Models\User; +use App\Services\CreditCardService; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpFoundation\Response; +use App\Http\Requests\LoginRequest; +use App\Services\UserService; + class AuthController extends Controller { + public function __construct(protected UserService $userService, protected CreditCardService $creditCardService) + { + } + public function register(Request $request): JsonResponse { $fields = $request->validate([ @@ -36,8 +45,7 @@ public function register(Request $request): JsonResponse 'user' => $user, ], Response::HTTP_CREATED); } catch (Exception $e) { - Log::error('User creation failed: '.$e->getMessage()); - + Log::error('User creation failed: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Registration failed. Please try again.', @@ -52,7 +60,7 @@ public function login(LoginRequest $request): JsonResponse $user = User::where('email', $credentials['email'])->first(); - if (! $user || ! Hash::check($credentials['password'], $user->password)) { + if (!$user || !Hash::check($credentials['password'], $user->password)) { throw ValidationException::withMessages([ 'email' => ['The provided credentials are incorrect.'], @@ -69,22 +77,14 @@ public function login(LoginRequest $request): JsonResponse ], Response::HTTP_OK); } - public function user(): UserResource + public function show(User $user): UserResource { - return new UserResource(auth()->user()); + return new UserResource($this->userService->show($user)); } - public function update(UserUpdateRequest $request): JsonResponse + public function update(UpdateUserRequest $request, User $user): UserResource { - $data = $request->validated(); - $user = auth()->user(); - - try { - $user->update($data); - } catch (Exception $e) { - return response()->json(['message' => "Failed to update user's profile!"], Response::HTTP_INTERNAL_SERVER_ERROR); - } + return new UserResource($this->userService->update($request->updateUser(), $user)); - return response()->json(['success' => true], Response::HTTP_OK); } } diff --git a/app/Http/Controllers/CreditCardController.php b/app/Http/Controllers/CreditCardController.php new file mode 100644 index 0000000..cc50af7 --- /dev/null +++ b/app/Http/Controllers/CreditCardController.php @@ -0,0 +1,24 @@ +creditCardService->show($user)); + } + public function update(UpdateCreditCardRequest $request, User $user): CreditCardResource + { + return new CreditCardResource($this->creditCardService->updateOrCreate($request->updateCard(), $user)); + } +} diff --git a/app/Http/Requests/UpdateCreditCardRequest.php b/app/Http/Requests/UpdateCreditCardRequest.php new file mode 100644 index 0000000..e6ff5dc --- /dev/null +++ b/app/Http/Requests/UpdateCreditCardRequest.php @@ -0,0 +1,30 @@ + 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', + 'card_last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', + 'card_number' => 'string|regex:/^\d{16}$/', + 'card_expiry_date' => 'string|regex:/^\d{2}\/\d{2}$/', + 'card_cvv' => 'string|regex:/^\d{3,4}$/', + ]; + } + + public function updateCard(): array + { + return $this->validated(); + } +} + diff --git a/app/Http/Requests/UserUpdateRequest.php b/app/Http/Requests/UpdateUserRequest.php similarity index 69% rename from app/Http/Requests/UserUpdateRequest.php rename to app/Http/Requests/UpdateUserRequest.php index 2e0b563..6b98f58 100644 --- a/app/Http/Requests/UserUpdateRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -4,7 +4,7 @@ use Illuminate\Foundation\Http\FormRequest; -class UserUpdateRequest extends FormRequest +class UpdateUserRequest extends FormRequest { /** * Determine if the user is authorized to make this request. @@ -24,19 +24,18 @@ public function rules(): array return [ 'name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', 'last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', - 'email' => 'email|max:255', + 'email' => 'email|max:255|unique:users,email', 'phone_number' => 'string|regex:/^\+?\d{9,15}$/', 'voivodship' => 'string|min:1|max:30', 'city' => 'string|min:1|max:30', 'zip_code' => 'string|regex:/^\d{2}-\d{3}$/', 'street' => 'string|min:1|max:30', 'house_number' => 'string|regex:/^\d+[a-zA-Z]?$/', - - 'card_first_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', - 'card_last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', - 'card_number' => 'string|regex:/^\d{16}$/', - 'card_expiry_date' => 'string|regex:/^\d{2}\/\d{2}$/', - 'card_cvv' => 'string|regex:/^\d{3,4}$/', ]; } + + public function updateUser(): array + { + return $this->validated(); + } } diff --git a/app/Http/Resources/CreditCardResource.php b/app/Http/Resources/CreditCardResource.php new file mode 100644 index 0000000..4723ff5 --- /dev/null +++ b/app/Http/Resources/CreditCardResource.php @@ -0,0 +1,36 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'card_first_name' => $this->card_first_name, + 'card_last_name' => $this->card_last_name, + 'card_number' => $this->maskCardNumber($this->card_number), + 'card_expiry_date' => $this->card_expiry_date, + 'card_cvv' => $this->maskCvv($this->card_cvv), + ]; + } + + private function maskCardNumber(string $cardNumber): string + { + // ############1234 + return str_repeat('#', strlen($cardNumber) - 4) . substr($cardNumber, -4); + } + + private function maskCvv(string $cvv): string + { + return str_repeat('*', strlen($cvv)); + } +} diff --git a/app/Models/CreditCard.php b/app/Models/CreditCard.php new file mode 100644 index 0000000..5b044fe --- /dev/null +++ b/app/Models/CreditCard.php @@ -0,0 +1,35 @@ + */ + use HasFactory; + protected $fillable = [ + 'user_id', + 'card_first_name', + 'card_last_name', + 'card_number', + 'card_expiry_date', + 'card_cvv', + ]; + protected function casts(): array + { + return [ + 'card_number' => 'hashed', + 'card_expiry_date' => 'hashed', + 'card_cvv' => 'hashed', + ]; + } + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 2253561..0356cbe 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,6 +5,7 @@ // use Illuminate\Contracts\Auth\MustVerifyEmail; use Database\Factories\UserFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; @@ -31,12 +32,6 @@ class User extends Authenticatable 'street', 'house_number', - 'card_first_name', - 'card_last_name', - 'card_number', - 'card_expiry_date', - 'card_cvv', - ]; /** @@ -61,4 +56,9 @@ protected function casts(): array 'password' => 'hashed', ]; } + + public function creditCard(): HasOne + { + return $this->hasOne(CreditCard::class); + } } diff --git a/app/Services/CreditCardService.php b/app/Services/CreditCardService.php new file mode 100644 index 0000000..652fb07 --- /dev/null +++ b/app/Services/CreditCardService.php @@ -0,0 +1,20 @@ +creditCard; + } + public function updateOrCreate(array $data, User $user): CreditCard + { + $creditCard = $user->creditCard(); + return $creditCard->updateOrCreate(['user_id' => $user->id], $data); + } +} diff --git a/app/Services/UserService.php b/app/Services/UserService.php new file mode 100644 index 0000000..e6b7d30 --- /dev/null +++ b/app/Services/UserService.php @@ -0,0 +1,19 @@ +update($data); + return $user; + } + +} diff --git a/database/factories/CreditCardFactory.php b/database/factories/CreditCardFactory.php new file mode 100644 index 0000000..29d68d8 --- /dev/null +++ b/database/factories/CreditCardFactory.php @@ -0,0 +1,29 @@ + + */ +class CreditCardFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'user_id' => User::factory(), + 'card_first_name' => fake()->card_first_name, + 'card_last_name' => fake()->card_last_name, + 'card_number' => fake()->card_number, + 'card_expiry_date' => fake()->card_expiry_date, + 'card_cvv' => fake()->card_cvv, + ]; + } +} diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 7926877..2e43f5e 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -26,12 +26,6 @@ public function up(): void $table->timestamp('email_verified_at')->nullable(); $table->string('password'); - $table->string('card_first_name')->nullable(); - $table->string('card_last_name')->nullable(); - $table->string('card_number')->nullable(); - $table->string('card_expiry_date')->nullable(); - $table->string('card_cvv')->nullable(); - $table->rememberToken(); $table->timestamps(); }); diff --git a/database/migrations/2024_12_18_090401_create_credit_cards_table.php b/database/migrations/2024_12_18_090401_create_credit_cards_table.php new file mode 100644 index 0000000..50f1020 --- /dev/null +++ b/database/migrations/2024_12_18_090401_create_credit_cards_table.php @@ -0,0 +1,33 @@ +id(); + $table->foreignId('user_id')->constrained(); + $table->string('card_first_name')->nullable(); + $table->string('card_last_name')->nullable(); + $table->string('card_number')->nullable(); + $table->string('card_expiry_date')->nullable(); + $table->string('card_cvv')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('credit_cards'); + } +}; diff --git a/routes/api.php b/routes/api.php index bc17238..63ed3d6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,17 +1,27 @@ group(function () { Route::controller(AuthController::class)->group(function () { - Route::get('user', 'user'); - Route::put('user', 'update'); + Route::get('user/{user}', 'show'); + Route::put('user/{user}', 'update'); + }); +}); + +Route::middleware('auth:sanctum')->group(function () { + Route::controller(CreditCardController::class)->group(function () { + Route::get('user/{user}/credit-card', 'show'); + Route::put('user/{user}/credit-card', 'update'); }); }); + + Route::get('/user', function (Request $request) { return $request->user(); })->middleware('auth:sanctum'); @@ -23,3 +33,5 @@ Route::get('/google/redirect', [GoogleAuthController::class, 'redirectToGoogle']); Route::get('/google/callback', [GoogleAuthController::class, 'handleGoogleCallback']); + + From 825e276c432c9519cb4e281c822c65b0ff50d803 Mon Sep 17 00:00:00 2001 From: frooooooo7 Date: Wed, 18 Dec 2024 12:29:37 +0000 Subject: [PATCH 4/7] PHP Linting (Pint) --- app/Http/Controllers/AuthController.php | 16 ++++++---------- app/Http/Controllers/CreditCardController.php | 5 ++--- app/Http/Requests/UpdateCreditCardRequest.php | 1 - app/Http/Resources/CreditCardResource.php | 2 +- app/Models/CreditCard.php | 2 ++ app/Services/CreditCardService.php | 3 ++- app/Services/UserService.php | 3 ++- routes/api.php | 5 +---- 8 files changed, 16 insertions(+), 21 deletions(-) diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 8eae8f2..c72067b 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -2,27 +2,22 @@ namespace App\Http\Controllers; -use App\Http\Requests\UpdateCreditCardRequest; +use App\Http\Requests\LoginRequest; use App\Http\Requests\UpdateUserRequest; use App\Http\Resources\UserResource; use App\Models\User; use App\Services\CreditCardService; +use App\Services\UserService; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpFoundation\Response; -use App\Http\Requests\LoginRequest; -use App\Services\UserService; - class AuthController extends Controller { - public function __construct(protected UserService $userService, protected CreditCardService $creditCardService) - { - } + public function __construct(protected UserService $userService, protected CreditCardService $creditCardService) {} public function register(Request $request): JsonResponse { @@ -45,7 +40,8 @@ public function register(Request $request): JsonResponse 'user' => $user, ], Response::HTTP_CREATED); } catch (Exception $e) { - Log::error('User creation failed: ' . $e->getMessage()); + Log::error('User creation failed: '.$e->getMessage()); + return response()->json([ 'success' => false, 'message' => 'Registration failed. Please try again.', @@ -60,7 +56,7 @@ public function login(LoginRequest $request): JsonResponse $user = User::where('email', $credentials['email'])->first(); - if (!$user || !Hash::check($credentials['password'], $user->password)) { + if (! $user || ! Hash::check($credentials['password'], $user->password)) { throw ValidationException::withMessages([ 'email' => ['The provided credentials are incorrect.'], diff --git a/app/Http/Controllers/CreditCardController.php b/app/Http/Controllers/CreditCardController.php index cc50af7..04aa94c 100644 --- a/app/Http/Controllers/CreditCardController.php +++ b/app/Http/Controllers/CreditCardController.php @@ -9,14 +9,13 @@ class CreditCardController extends Controller { - public function __construct(protected CreditCardService $creditCardService) - { - } + public function __construct(protected CreditCardService $creditCardService) {} public function show(User $user): CreditCardResource { return new CreditCardResource($this->creditCardService->show($user)); } + public function update(UpdateCreditCardRequest $request, User $user): CreditCardResource { return new CreditCardResource($this->creditCardService->updateOrCreate($request->updateCard(), $user)); diff --git a/app/Http/Requests/UpdateCreditCardRequest.php b/app/Http/Requests/UpdateCreditCardRequest.php index e6ff5dc..0ff2904 100644 --- a/app/Http/Requests/UpdateCreditCardRequest.php +++ b/app/Http/Requests/UpdateCreditCardRequest.php @@ -27,4 +27,3 @@ public function updateCard(): array return $this->validated(); } } - diff --git a/app/Http/Resources/CreditCardResource.php b/app/Http/Resources/CreditCardResource.php index 4723ff5..da85cdc 100644 --- a/app/Http/Resources/CreditCardResource.php +++ b/app/Http/Resources/CreditCardResource.php @@ -26,7 +26,7 @@ public function toArray(Request $request): array private function maskCardNumber(string $cardNumber): string { // ############1234 - return str_repeat('#', strlen($cardNumber) - 4) . substr($cardNumber, -4); + return str_repeat('#', strlen($cardNumber) - 4).substr($cardNumber, -4); } private function maskCvv(string $cvv): string diff --git a/app/Models/CreditCard.php b/app/Models/CreditCard.php index 5b044fe..99a005f 100644 --- a/app/Models/CreditCard.php +++ b/app/Models/CreditCard.php @@ -11,6 +11,7 @@ class CreditCard extends Model { /** @use HasFactory */ use HasFactory; + protected $fillable = [ 'user_id', 'card_first_name', @@ -19,6 +20,7 @@ class CreditCard extends Model 'card_expiry_date', 'card_cvv', ]; + protected function casts(): array { return [ diff --git a/app/Services/CreditCardService.php b/app/Services/CreditCardService.php index 652fb07..a203363 100644 --- a/app/Services/CreditCardService.php +++ b/app/Services/CreditCardService.php @@ -7,14 +7,15 @@ class CreditCardService { - public function show(User $user): CreditCard { return $user->creditCard; } + public function updateOrCreate(array $data, User $user): CreditCard { $creditCard = $user->creditCard(); + return $creditCard->updateOrCreate(['user_id' => $user->id], $data); } } diff --git a/app/Services/UserService.php b/app/Services/UserService.php index e6b7d30..20f0383 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -10,10 +10,11 @@ public function show(User $user): User { return $user; } + public function update(array $data, User $user): User { $user->update($data); + return $user; } - } diff --git a/routes/api.php b/routes/api.php index 63ed3d6..623a665 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,7 +1,7 @@ user(); })->middleware('auth:sanctum'); @@ -33,5 +32,3 @@ Route::get('/google/redirect', [GoogleAuthController::class, 'redirectToGoogle']); Route::get('/google/callback', [GoogleAuthController::class, 'handleGoogleCallback']); - - From 30aa0aa1fa5b68994feb878ec091e1a78e940d88 Mon Sep 17 00:00:00 2001 From: frois Date: Fri, 20 Dec 2024 13:33:25 +0100 Subject: [PATCH 5/7] fix: in UpdateUserRequest unique email --- app/Http/Requests/UpdateUserRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php index 6b98f58..fe36410 100644 --- a/app/Http/Requests/UpdateUserRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -24,7 +24,7 @@ public function rules(): array return [ 'name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', 'last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', - 'email' => 'email|max:255|unique:users,email', + 'email' => 'email|max:255|unique:users,email,' . $this->user->id, 'phone_number' => 'string|regex:/^\+?\d{9,15}$/', 'voivodship' => 'string|min:1|max:30', 'city' => 'string|min:1|max:30', From 2b1ae38a92b3dfed2d6223d57c37a48692ebc62f Mon Sep 17 00:00:00 2001 From: frooooooo7 Date: Fri, 20 Dec 2024 12:34:20 +0000 Subject: [PATCH 6/7] PHP Linting (Pint) --- app/Http/Requests/UpdateUserRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php index fe36410..8fa2c60 100644 --- a/app/Http/Requests/UpdateUserRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -24,7 +24,7 @@ public function rules(): array return [ 'name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', 'last_name' => 'string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/', - 'email' => 'email|max:255|unique:users,email,' . $this->user->id, + 'email' => 'email|max:255|unique:users,email,'.$this->user->id, 'phone_number' => 'string|regex:/^\+?\d{9,15}$/', 'voivodship' => 'string|min:1|max:30', 'city' => 'string|min:1|max:30', From a081a7eb759d6fa24db0941be38631f64fb93685 Mon Sep 17 00:00:00 2001 From: frois Date: Fri, 20 Dec 2024 14:28:36 +0100 Subject: [PATCH 7/7] fix: --- app/Models/CreditCard.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Models/CreditCard.php b/app/Models/CreditCard.php index 99a005f..4ff1488 100644 --- a/app/Models/CreditCard.php +++ b/app/Models/CreditCard.php @@ -25,7 +25,6 @@ protected function casts(): array { return [ 'card_number' => 'hashed', - 'card_expiry_date' => 'hashed', 'card_cvv' => 'hashed', ]; }