refactor(requests): extract user-owned exists rules to trait (#477)
## What
The `Rule::exists('x', 'id')->where(fn => user_id)` ownership closure
was repeated **19×** across 10 Form Requests (categories, labels,
accounts, typed accounts).
New `app/Http/Requests/Concerns/ValidatesUserOwnedResources` trait:
- `$this->userOwned('categories' | 'labels' | 'accounts')`
- `$this->userOwnedAccountOfType(AccountType::Loan | RealEstate)`
`UpdateAutomationRuleRequest` intentionally untouched — #476 makes it
extend Store.
## Stats
- **-110 / +63 lines**
## Checks
- `php artisan test
--filter="Transaction|Budget|Account|AutomationRule|RealEstate|Loan"` —
641 passed (3052 assertions), 1 skipped
- `vendor/bin/pint --dirty` — pass
Part of duplication-removal series (#475, #476).
This commit is contained in:
parent
65acab4512
commit
cc63a86a1c
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class BulkUpdateTransactionsRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
|
|
@ -23,44 +25,20 @@ class BulkUpdateTransactionsRequest extends FormRequest
|
|||
'filters.amount_min' => ['nullable', 'numeric'],
|
||||
'filters.amount_max' => ['nullable', 'numeric'],
|
||||
'filters.category_ids' => ['nullable', 'array'],
|
||||
'filters.category_ids.*' => [
|
||||
'string',
|
||||
'uuid',
|
||||
Rule::exists('categories', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'filters.category_ids.*' => ['string', 'uuid', $this->userOwned('categories')],
|
||||
'filters.account_ids' => ['nullable', 'array'],
|
||||
'filters.account_ids.*' => ['string', 'uuid'],
|
||||
'filters.label_ids' => ['nullable', 'array'],
|
||||
'filters.label_ids.*' => [
|
||||
'string',
|
||||
'uuid',
|
||||
Rule::exists('labels', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'filters.label_ids.*' => ['string', 'uuid', $this->userOwned('labels')],
|
||||
'filters.creditor_name' => ['nullable', 'string'],
|
||||
'filters.debtor_name' => ['nullable', 'string'],
|
||||
'filters.search' => ['nullable', 'string'],
|
||||
'filters.search_text' => ['nullable', 'string'],
|
||||
'category_id' => [
|
||||
'nullable',
|
||||
Rule::exists('categories', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'category_id' => ['nullable', $this->userOwned('categories')],
|
||||
'notes' => ['nullable', 'string'],
|
||||
'notes_iv' => ['nullable', 'string', 'size:16'],
|
||||
'label_ids' => ['nullable', 'array'],
|
||||
'label_ids.*' => [
|
||||
'required',
|
||||
'string',
|
||||
'uuid',
|
||||
Rule::exists('labels', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'label_ids.*' => ['required', 'string', 'uuid', $this->userOwned('labels')],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Concerns;
|
||||
|
||||
use App\Enums\AccountType;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Rules\Exists;
|
||||
|
||||
trait ValidatesUserOwnedResources
|
||||
{
|
||||
/**
|
||||
* Rule asserting the value references a record on the given table owned by the authenticated user.
|
||||
*/
|
||||
protected function userOwned(string $table): Exists
|
||||
{
|
||||
return Rule::exists($table, 'id')->where('user_id', $this->user()->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rule asserting the value references an account of the given type owned by the authenticated user.
|
||||
*/
|
||||
protected function userOwnedAccountOfType(AccountType $type): Exists
|
||||
{
|
||||
return $this->userOwned('accounts')->where('type', $type->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
namespace App\Http\Requests\OpenBanking;
|
||||
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class MapAccountsRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return $this->route('connection')->user_id === $this->user()->id;
|
||||
|
|
@ -25,7 +27,7 @@ class MapAccountsRequest extends FormRequest
|
|||
'nullable',
|
||||
'uuid',
|
||||
'required_if:mappings.*.action,link',
|
||||
Rule::exists('accounts', 'id')->where('user_id', $this->user()->id),
|
||||
$this->userOwned('accounts'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Requests\Settings;
|
|||
|
||||
use App\Enums\AccountType;
|
||||
use App\Enums\PropertyType;
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use App\Models\Account;
|
||||
use App\Services\CurrencyOptions;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
|
@ -12,6 +13,8 @@ use Illuminate\Validation\Rule;
|
|||
|
||||
class StoreAccountRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
|
|
@ -64,10 +67,7 @@ class StoreAccountRequest extends FormRequest
|
|||
'linked_loan_account_id' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::exists('accounts', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id)
|
||||
->where('type', AccountType::Loan->value);
|
||||
}),
|
||||
$this->userOwnedAccountOfType(AccountType::Loan),
|
||||
],
|
||||
'notes' => ['nullable', 'string', 'max:2000'],
|
||||
'revaluation_percentage' => ['nullable', 'numeric', 'min:-100', 'max:100'],
|
||||
|
|
@ -85,10 +85,7 @@ class StoreAccountRequest extends FormRequest
|
|||
'linked_real_estate_account_id' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::exists('accounts', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id)
|
||||
->where('type', AccountType::RealEstate->value);
|
||||
}),
|
||||
$this->userOwnedAccountOfType(AccountType::RealEstate),
|
||||
function (string $attribute, mixed $value, \Closure $fail): void {
|
||||
if (! is_string($value)) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
namespace App\Http\Requests\Settings;
|
||||
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreAutomationRuleRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
|
|
@ -35,9 +37,7 @@ class StoreAutomationRuleRequest extends FormRequest
|
|||
'action_category_id' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::exists('categories', 'id')->where(function ($query) {
|
||||
$query->where('user_id', auth()->id());
|
||||
}),
|
||||
$this->userOwned('categories'),
|
||||
],
|
||||
'action_note' => ['nullable', 'string'],
|
||||
'action_note_iv' => ['nullable', 'string', 'required_with:action_note'],
|
||||
|
|
@ -46,9 +46,7 @@ class StoreAutomationRuleRequest extends FormRequest
|
|||
'required',
|
||||
'string',
|
||||
'uuid',
|
||||
Rule::exists('labels', 'id')->where(function ($query) {
|
||||
$query->where('user_id', auth()->id());
|
||||
}),
|
||||
$this->userOwned('labels'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Requests\Settings;
|
|||
|
||||
use App\Enums\AccountType;
|
||||
use App\Enums\PropertyType;
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use App\Services\CurrencyOptions;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
|
@ -11,6 +12,8 @@ use Illuminate\Validation\Rule;
|
|||
|
||||
class UpdateAccountRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
|
|
@ -59,10 +62,7 @@ class UpdateAccountRequest extends FormRequest
|
|||
'linked_loan_account_id' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::exists('accounts', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id)
|
||||
->where('type', AccountType::Loan->value);
|
||||
}),
|
||||
$this->userOwnedAccountOfType(AccountType::Loan),
|
||||
],
|
||||
'notes' => ['nullable', 'string', 'max:2000'],
|
||||
'revaluation_percentage' => ['nullable', 'numeric', 'min:-100', 'max:100'],
|
||||
|
|
|
|||
|
|
@ -4,11 +4,14 @@ namespace App\Http\Requests;
|
|||
|
||||
use App\Enums\BudgetPeriodType;
|
||||
use App\Enums\RolloverType;
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreBudgetRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
|
|
@ -16,16 +19,14 @@ class StoreBudgetRequest extends FormRequest
|
|||
|
||||
public function rules(): array
|
||||
{
|
||||
$userId = $this->user()->id;
|
||||
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'period_type' => ['required', Rule::enum(BudgetPeriodType::class)],
|
||||
'period_start_day' => ['nullable', 'integer', 'min:0', 'max:31'],
|
||||
'category_ids' => ['nullable', 'array'],
|
||||
'category_ids.*' => [Rule::exists('categories', 'id')->where('user_id', $userId)],
|
||||
'category_ids.*' => [$this->userOwned('categories')],
|
||||
'label_ids' => ['nullable', 'array'],
|
||||
'label_ids.*' => [Rule::exists('labels', 'id')->where('user_id', $userId)],
|
||||
'label_ids.*' => [$this->userOwned('labels')],
|
||||
'rollover_type' => ['required', Rule::enum(RolloverType::class)],
|
||||
'allocated_amount' => ['required', 'integer', 'min:0'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@ namespace App\Http\Requests;
|
|||
|
||||
use App\Enums\AccountType;
|
||||
use App\Enums\PropertyType;
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreRealEstateDetailRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
|
|
@ -39,10 +42,7 @@ class StoreRealEstateDetailRequest extends FormRequest
|
|||
'linked_loan_account_id' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::exists('accounts', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id)
|
||||
->where('type', AccountType::Loan->value);
|
||||
}),
|
||||
$this->userOwnedAccountOfType(AccountType::Loan),
|
||||
],
|
||||
'notes' => ['nullable', 'string', 'max:2000'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@
|
|||
namespace App\Http\Requests;
|
||||
|
||||
use App\Enums\TransactionSource;
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreTransactionRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
|
|
@ -17,18 +20,8 @@ class StoreTransactionRequest extends FormRequest
|
|||
{
|
||||
return [
|
||||
'id' => ['sometimes', 'uuid'],
|
||||
'account_id' => [
|
||||
'required',
|
||||
Rule::exists('accounts', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'category_id' => [
|
||||
'nullable',
|
||||
Rule::exists('categories', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'account_id' => ['required', $this->userOwned('accounts')],
|
||||
'category_id' => ['nullable', $this->userOwned('categories')],
|
||||
'description' => ['required', 'string'],
|
||||
'description_iv' => ['nullable', 'string', 'size:16'],
|
||||
'transaction_date' => ['required', 'date'],
|
||||
|
|
@ -40,13 +33,7 @@ class StoreTransactionRequest extends FormRequest
|
|||
'debtor_name' => ['nullable', 'string', 'max:255'],
|
||||
'source' => ['required', Rule::enum(TransactionSource::class)],
|
||||
'label_ids' => ['nullable', 'array'],
|
||||
'label_ids.*' => [
|
||||
'string',
|
||||
'uuid',
|
||||
Rule::exists('labels', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'label_ids.*' => ['string', 'uuid', $this->userOwned('labels')],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@ namespace App\Http\Requests;
|
|||
|
||||
use App\Enums\AccountType;
|
||||
use App\Enums\PropertyType;
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateRealEstateDetailRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
|
|
@ -40,10 +43,7 @@ class UpdateRealEstateDetailRequest extends FormRequest
|
|||
'linked_loan_account_id' => [
|
||||
'nullable',
|
||||
'string',
|
||||
Rule::exists('accounts', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id)
|
||||
->where('type', AccountType::Loan->value);
|
||||
}),
|
||||
$this->userOwnedAccountOfType(AccountType::Loan),
|
||||
],
|
||||
'notes' => ['nullable', 'string', 'max:2000'],
|
||||
'revaluation_percentage' => ['nullable', 'numeric', 'min:-100', 'max:100'],
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Concerns\ValidatesUserOwnedResources;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateTransactionRequest extends FormRequest
|
||||
{
|
||||
use ValidatesUserOwnedResources;
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
|
|
@ -15,12 +17,7 @@ class UpdateTransactionRequest extends FormRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'category_id' => [
|
||||
'nullable',
|
||||
Rule::exists('categories', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'category_id' => ['nullable', $this->userOwned('categories')],
|
||||
'description' => ['sometimes', 'string'],
|
||||
'description_iv' => ['nullable', 'string', 'size:16'],
|
||||
'notes' => ['nullable', 'string'],
|
||||
|
|
@ -28,14 +25,7 @@ class UpdateTransactionRequest extends FormRequest
|
|||
'creditor_name' => ['nullable', 'string', 'max:255'],
|
||||
'debtor_name' => ['nullable', 'string', 'max:255'],
|
||||
'label_ids' => ['nullable', 'array'],
|
||||
'label_ids.*' => [
|
||||
'required',
|
||||
'string',
|
||||
'uuid',
|
||||
Rule::exists('labels', 'id')->where(function ($query) {
|
||||
$query->where('user_id', $this->user()->id);
|
||||
}),
|
||||
],
|
||||
'label_ids.*' => ['required', 'string', 'uuid', $this->userOwned('labels')],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue