diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 7ac6dcee34d3..1a98f29dd0b7 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -171,7 +171,7 @@ class LoginController extends BaseController //if user has 2fa enabled - lets check this now: - if($user->google_2fa_secret && $request->has('one_time_password')) + if($user->google_2fa_secret && $request->has('one_time_password') && strlen($request->input('one_time_password')) >= 1) { $google2fa = new Google2FA(); @@ -194,6 +194,7 @@ class LoginController extends BaseController $user->setCompany($user->account->default_company); $timeout = auth()->user()->company()->default_password_timeout; + Cache::put(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout); $cu = CompanyUser::query() @@ -322,33 +323,34 @@ class LoginController extends BaseController if ($user) { - $client = new Google_Client(); - $client->setClientId(config('ninja.auth.google.client_id')); - $client->setClientSecret(config('ninja.auth.google.client_secret')); - $client->setRedirectUri(config('ninja.app_url')); + // we are no longer accessing the permissions for gmail - email permissions here - $token = false; + // $client = new Google_Client(); + // $client->setClientId(config('ninja.auth.google.client_id')); + // $client->setClientSecret(config('ninja.auth.google.client_secret')); + // $client->setRedirectUri(config('ninja.app_url')); - try{ - $token = $client->authenticate(request()->input('server_auth_code')); - } - catch(\Exception $e) { + // $token = false; - return response() - ->json(['message' => ctrans('texts.invalid_credentials')], 401) - ->header('X-App-Version', config('ninja.app_version')) - ->header('X-Api-Version', config('ninja.minimum_client_version')); + // try{ + // $token = $client->authenticate(request()->input('server_auth_code')); + // } + // catch(\Exception $e) { - } + // return response() + // ->json(['message' => ctrans('texts.invalid_credentials')], 401) + // ->header('X-App-Version', config('ninja.app_version')) + // ->header('X-Api-Version', config('ninja.minimum_client_version')); - $refresh_token = ''; + // } - if (array_key_exists('refresh_token', $token)) { - $refresh_token = $token['refresh_token']; - } + // $refresh_token = ''; - //$access_token = $token['access_token']; + // if (array_key_exists('refresh_token', $token)) { + // $refresh_token = $token['refresh_token']; + // } + $name = OAuth::splitName($google->harvestName($user)); $new_account = [ diff --git a/app/Http/Middleware/QueryLogging.php b/app/Http/Middleware/QueryLogging.php index 92aee1a2046b..b898814f6855 100644 --- a/app/Http/Middleware/QueryLogging.php +++ b/app/Http/Middleware/QueryLogging.php @@ -54,7 +54,7 @@ class QueryLogging nlog($request->method().' - '.$request->url().": $count queries - ".$time); // if($count > 50) - // Log::nlog($queries); + //nlog($queries); } } diff --git a/app/Http/Requests/Client/StoreClientRequest.php b/app/Http/Requests/Client/StoreClientRequest.php index b9cb4f1a15d6..313ee11eb6ae 100644 --- a/app/Http/Requests/Client/StoreClientRequest.php +++ b/app/Http/Requests/Client/StoreClientRequest.php @@ -19,6 +19,7 @@ use App\Models\Client; use App\Models\GroupSetting; use App\Utils\Traits\MakesHash; use Illuminate\Support\Facades\Cache; +use Illuminate\Validation\Rule; class StoreClientRequest extends Request { @@ -48,7 +49,6 @@ class StoreClientRequest extends Request /* Ensure we have a client name, and that all emails are unique*/ //$rules['name'] = 'required|min:1'; - $rules['id_number'] = 'unique:clients,id_number,'.$this->id.',id,company_id,'.$this->company_id; $rules['settings'] = new ValidClientGroupSettingsRule(); $rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email'; $rules['contacts.*.password'] = [ @@ -66,6 +66,10 @@ class StoreClientRequest extends Request $rules['hosted_clients'] = new CanStoreClientsRule($this->company_id); } + $rules['number'] = ['nullable',Rule::unique('clients')->where('company_id', auth()->user()->company()->id)]; + $rules['id_number'] = ['nullable',Rule::unique('clients')->where('company_id', auth()->user()->company()->id)]; + + return $rules; } @@ -122,7 +126,7 @@ class StoreClientRequest extends Request public function messages() { return [ - 'unique' => ctrans('validation.unique', ['attribute' => 'email']), + // 'unique' => ctrans('validation.unique', ['attribute' => ['email','number']), //'required' => trans('validation.required', ['attribute' => 'email']), 'contacts.*.email.required' => ctrans('validation.email', ['attribute' => 'email']), ]; diff --git a/app/Http/Requests/Client/UpdateClientRequest.php b/app/Http/Requests/Client/UpdateClientRequest.php index e322ad0a29f3..c230597960ae 100644 --- a/app/Http/Requests/Client/UpdateClientRequest.php +++ b/app/Http/Requests/Client/UpdateClientRequest.php @@ -16,6 +16,7 @@ use App\Http\Requests\Request; use App\Http\ValidationRules\ValidClientGroupSettingsRule; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; class UpdateClientRequest extends Request { @@ -52,7 +53,14 @@ class UpdateClientRequest extends Request $rules['country_id'] = 'integer|nullable'; $rules['shipping_country_id'] = 'integer|nullable'; //$rules['id_number'] = 'unique:clients,id_number,,id,company_id,' . auth()->user()->company()->id; - $rules['id_number'] = 'unique:clients,id_number,'.$this->id.',id,company_id,'.$this->company_id; + //$rules['id_number'] = 'unique:clients,id_number,'.$this->id.',id,company_id,'.$this->company_id; + + if($this->id_number) + $rules['id_number'] = Rule::unique('clients')->where('company_id', auth()->user()->company()->id)->ignore($this->client->id); + + if($this->number) + $rules['number'] = Rule::unique('clients')->where('company_id', auth()->user()->company()->id)->ignore($this->client->id); + $rules['settings'] = new ValidClientGroupSettingsRule(); $rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email'; $rules['contacts.*.password'] = [ @@ -72,7 +80,6 @@ class UpdateClientRequest extends Request public function messages() { return [ - 'unique' => ctrans('validation.unique', ['attribute' => 'email']), 'email' => ctrans('validation.email', ['attribute' => 'email']), 'name.required' => ctrans('validation.required', ['attribute' => 'name']), 'required' => ctrans('validation.required', ['attribute' => 'email']), diff --git a/app/Http/Requests/Credit/UpdateCreditRequest.php b/app/Http/Requests/Credit/UpdateCreditRequest.php index 426301ef39b4..2c7c43d39bf9 100644 --- a/app/Http/Requests/Credit/UpdateCreditRequest.php +++ b/app/Http/Requests/Credit/UpdateCreditRequest.php @@ -16,6 +16,7 @@ use App\Http\Requests\Request; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; class UpdateCreditRequest extends Request { @@ -52,9 +53,8 @@ class UpdateCreditRequest extends Request $rules['documents'] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; } - if ($this->input('number')) { - $rules['number'] = 'unique:credits,number,'.$this->id.',id,company_id,'.$this->credit->company_id; - } + if($this->number) + $rules['number'] = Rule::unique('credits')->where('company_id', auth()->user()->company()->id)->ignore($this->credit->id); $rules['line_items'] = 'array'; diff --git a/app/Http/Requests/Expense/StoreExpenseRequest.php b/app/Http/Requests/Expense/StoreExpenseRequest.php index 828217b4ee63..3a4726867d97 100644 --- a/app/Http/Requests/Expense/StoreExpenseRequest.php +++ b/app/Http/Requests/Expense/StoreExpenseRequest.php @@ -35,10 +35,9 @@ class StoreExpenseRequest extends Request { $rules = []; - if (isset($this->number)) { + if ($this->number) $rules['number'] = Rule::unique('expenses')->where('company_id', auth()->user()->company()->id); - } - + if(!empty($this->client_id)) $rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id; diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 7234211d1884..0fb69a64e3f6 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -16,6 +16,7 @@ use App\Http\ValidationRules\Invoice\LockedInvoiceRule; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; class UpdateInvoiceRequest extends Request { @@ -49,10 +50,8 @@ class UpdateInvoiceRequest extends Request $rules['id'] = new LockedInvoiceRule($this->invoice); - // if ($this->input('number') && strlen($this->input('number')) >= 1) { - if ($this->input('number')) { - $rules['number'] = 'unique:invoices,number,'.$this->id.',id,company_id,'.$this->invoice->company_id; - } + if($this->number) + $rules['number'] = Rule::unique('invoices')->where('company_id', auth()->user()->company()->id)->ignore($this->invoice->id); $rules['line_items'] = 'array'; diff --git a/app/Http/Requests/Payment/UpdatePaymentRequest.php b/app/Http/Requests/Payment/UpdatePaymentRequest.php index e5436b55bb12..9f921821dc45 100644 --- a/app/Http/Requests/Payment/UpdatePaymentRequest.php +++ b/app/Http/Requests/Payment/UpdatePaymentRequest.php @@ -16,6 +16,7 @@ use App\Http\ValidationRules\PaymentAppliedValidAmount; use App\Http\ValidationRules\ValidCreditsPresentRule; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; class UpdatePaymentRequest extends Request { @@ -35,12 +36,14 @@ class UpdatePaymentRequest extends Request public function rules() { $rules = [ - 'number' => 'nullable|unique:payments,number,'.$this->id.',id,company_id,'.$this->payment->company_id, 'invoices' => ['array', new PaymentAppliedValidAmount, new ValidCreditsPresentRule], 'invoices.*.invoice_id' => 'distinct', 'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx', ]; + if($this->number) + $rules['number'] = Rule::unique('payments')->where('company_id', auth()->user()->company()->id)->ignore($this->payment->id); + if ($this->input('documents') && is_array($this->input('documents'))) { $documents = count($this->input('documents')); diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php index 019c630aac3d..6ce240c6bae1 100644 --- a/app/Http/Requests/Quote/UpdateQuoteRequest.php +++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php @@ -15,6 +15,7 @@ use App\Http\Requests\Request; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; class UpdateQuoteRequest extends Request { @@ -46,9 +47,8 @@ class UpdateQuoteRequest extends Request $rules['documents'] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; } - if ($this->input('number')) { - $rules['number'] = 'unique:quotes,number,'.$this->id.',id,company_id,'.$this->quote->company_id; - } + if($this->number) + $rules['number'] = Rule::unique('quotes')->where('company_id', auth()->user()->company()->id)->ignore($this->quote->id); $rules['line_items'] = 'array'; diff --git a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php index 6d6609534247..7156974c233c 100644 --- a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php @@ -16,6 +16,7 @@ use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; use Illuminate\Http\UploadedFile; +use Illuminate\Validation\Rule; class UpdateRecurringInvoiceRequest extends Request { @@ -47,9 +48,9 @@ class UpdateRecurringInvoiceRequest extends Request $rules['documents'] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; } - if ($this->input('number')) { - $rules['number'] = 'unique:recurring_invoices,number,'.$this->recurring_invoice->id.',id,company_id,'.$this->recurring_invoice->company_id; - } + if($this->number) + $rules['number'] = Rule::unique('recurring_invoices')->where('company_id', auth()->user()->company()->id)->ignore($this->recurring_invoice->id); + return $rules; } diff --git a/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php b/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php index 7a05426a1568..8527cba80c2a 100644 --- a/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php +++ b/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php @@ -14,6 +14,7 @@ namespace App\Http\Requests\RecurringQuote; use App\Http\Requests\Request; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\CleanLineItems; +use Illuminate\Validation\Rule; class UpdateRecurringQuoteRequest extends Request { @@ -47,6 +48,9 @@ class UpdateRecurringQuoteRequest extends Request $input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : []; + if($this->number) + $rules['number'] = Rule::unique('recurring_quotes')->where('company_id', auth()->user()->company()->id)->ignore($this->recurring_quote->id); + $this->replace($input); } } diff --git a/app/Http/Requests/TaxRate/UpdateTaxRateRequest.php b/app/Http/Requests/TaxRate/UpdateTaxRateRequest.php index 949630e58ab7..ea11b59f37e5 100644 --- a/app/Http/Requests/TaxRate/UpdateTaxRateRequest.php +++ b/app/Http/Requests/TaxRate/UpdateTaxRateRequest.php @@ -12,6 +12,7 @@ namespace App\Http\Requests\TaxRate; use App\Http\Requests\Request; +use Illuminate\Validation\Rule; class UpdateTaxRateRequest extends Request { @@ -27,10 +28,14 @@ class UpdateTaxRateRequest extends Request public function rules() { - return [ - // 'name' => 'unique:tax_rates,name,'.$this->tax_rate->name.',id,company_id,'.auth()->user()->companyId(), - 'name' => 'unique:tax_rates,name,'.$this->id.',id,company_id,'.$this->company_id, - 'rate' => 'numeric', - ]; + $rules = []; + + $rules['rate'] = 'numeric'; + + if($this->number) + $rules['number'] = Rule::unique('tax_rates')->where('company_id', auth()->user()->company()->id)->ignore($this->tax_rate->id); + + return $rules; + } } diff --git a/app/Http/Requests/Vendor/UpdateVendorRequest.php b/app/Http/Requests/Vendor/UpdateVendorRequest.php index 2c7038492d93..14f334e278d0 100644 --- a/app/Http/Requests/Vendor/UpdateVendorRequest.php +++ b/app/Http/Requests/Vendor/UpdateVendorRequest.php @@ -14,6 +14,7 @@ namespace App\Http\Requests\Vendor; use App\Http\Requests\Request; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; class UpdateVendorRequest extends Request { @@ -35,18 +36,15 @@ class UpdateVendorRequest extends Request /* Ensure we have a client name, and that all emails are unique*/ $rules['country_id'] = 'integer|nullable'; - //$rules['id_number'] = 'unique:clients,id_number,,id,company_id,' . auth()->user()->company()->id; - $rules['id_number'] = 'unique:clients,id_number,'.$this->id.',id,company_id,'.$this->company_id; + + if($this->number) + $rules['number'] = Rule::unique('vendors')->where('company_id', auth()->user()->company()->id)->ignore($this->vendor->id); + + if($this->id_number) + $rules['id_number'] = Rule::unique('vendors')->where('company_id', auth()->user()->company()->id)->ignore($this->vendor->id); + $rules['contacts.*.email'] = 'nullable|distinct'; - $contacts = request('contacts'); - - if (is_array($contacts)) { - // for ($i = 0; $i < count($contacts); $i++) { - // // $rules['contacts.' . $i . '.email'] = 'nullable|email|unique:client_contacts,email,' . isset($contacts[$i]['id'].',company_id,'.$this->company_id); - // //$rules['contacts.' . $i . '.email'] = 'nullable|email'; - // } - } return $rules; } @@ -54,7 +52,6 @@ class UpdateVendorRequest extends Request public function messages() { return [ - 'unique' => ctrans('validation.unique', ['attribute' => 'email']), 'email' => ctrans('validation.email', ['attribute' => 'email']), 'name.required' => ctrans('validation.required', ['attribute' => 'name']), 'required' => ctrans('validation.required', ['attribute' => 'email']), diff --git a/app/Models/Project.php b/app/Models/Project.php index 42b84cbbaa29..daf67ad2d1e8 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -37,6 +37,7 @@ class Project extends BaseModel 'custom_value4', 'assigned_user_id', 'color', + 'number', ]; public function getEntityType() diff --git a/database/migrations/2021_03_19_221024_add_unique_constraints_on_all_entities.php b/database/migrations/2021_03_19_221024_add_unique_constraints_on_all_entities.php new file mode 100644 index 000000000000..a1a1d2d01921 --- /dev/null +++ b/database/migrations/2021_03_19_221024_add_unique_constraints_on_all_entities.php @@ -0,0 +1,65 @@ +unique(['company_id', 'number']); + }); + + Schema::table('tasks', function (Blueprint $table) { + $table->unique(['company_id', 'number']); + }); + + Schema::table('vendors', function (Blueprint $table) { + $table->unique(['company_id', 'number']); + }); + + Schema::table('payments', function (Blueprint $table) { + $table->unique(['company_id', 'number']); + }); + + Schema::table('projects', function (Blueprint $table) { + $table->unique(['company_id', 'number']); + }); + + Schema::table('clients', function (Blueprint $table) { + $table->unique(['company_id', 'number']); + }); + + Schema::table('payment_hashes', function (Blueprint $table) { + $table->unique(['hash']); + }); + + Schema::table('recurring_invoices', function (Blueprint $table) { + $table->string('number')->change(); + $table->unique(['company_id', 'number']); + }); + + Schema::table('recurring_invoice_invitations', function (Blueprint $table) { + $table->unique(['client_contact_id', 'recurring_invoice_id'],'recur_invoice_client_unique'); + }); + + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/tests/Feature/ClientApiTest.php b/tests/Feature/ClientApiTest.php index 3c87a5e07633..affd7461d3c6 100644 --- a/tests/Feature/ClientApiTest.php +++ b/tests/Feature/ClientApiTest.php @@ -54,6 +54,28 @@ class ClientApiTest extends TestCase $response->assertStatus(200); } + public function testDuplicateNumberCatch() + { + $data = [ + 'name' => $this->faker->firstName, + 'number' => 'iamaduplicate', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients', $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients', $data); + + $response->assertStatus(302); + } + public function testClientPut() { $data = [ @@ -67,6 +89,20 @@ class ClientApiTest extends TestCase ])->put('/api/v1/clients/'.$this->encodePrimaryKey($this->client->id), $data); $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/clients/'.$this->encodePrimaryKey($this->client->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients/', $data); + + $response->assertStatus(302); } public function testClientGet() diff --git a/tests/Feature/CreditTest.php b/tests/Feature/CreditTest.php index 936a10b6978d..0562f2fd16a7 100644 --- a/tests/Feature/CreditTest.php +++ b/tests/Feature/CreditTest.php @@ -131,4 +131,80 @@ class CreditTest extends TestCase $response->assertStatus(200); } + + public function testDuplicateNumberCatch() + { + $data = [ + 'status_id' => 1, + 'number' => 'dfdfd', + 'discount' => 0, + 'is_amount_discount' => 1, + 'number' => '3434343', + 'public_notes' => 'notes', + 'is_deleted' => 0, + 'custom_value1' => 0, + 'custom_value2' => 0, + 'custom_value3' => 0, + 'custom_value4' => 0, + 'status' => 1, + 'client_id' => $this->encodePrimaryKey($this->client->id), + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/credits', $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/credits', $data); + + $response->assertStatus(302); + } + + public function testCreditPut() + { + $data = [ + 'status_id' => 1, + 'number' => 'dfdfd', + 'discount' => 0, + 'is_amount_discount' => 1, + 'number' => '3434343', + 'public_notes' => 'notes', + 'is_deleted' => 0, + 'custom_value1' => 0, + 'custom_value2' => 0, + 'custom_value3' => 0, + 'custom_value4' => 0, + 'status' => 1, + 'client_id' => $this->encodePrimaryKey($this->client->id), + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/credits/'.$this->encodePrimaryKey($this->credit->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/credits/'.$this->encodePrimaryKey($this->credit->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/credits/', $data); + + $response->assertStatus(302); + } + + + } diff --git a/tests/Feature/ExpenseApiTest.php b/tests/Feature/ExpenseApiTest.php index f17aeb5362b7..70254f13b67a 100644 --- a/tests/Feature/ExpenseApiTest.php +++ b/tests/Feature/ExpenseApiTest.php @@ -57,11 +57,34 @@ class ExpenseApiTest extends TestCase $this->assertNotEmpty($arr['data']['number']); } + public function testDuplicateNumberCatch() + { + $data = [ + 'public_notes' => $this->faker->firstName, + 'number' => 'iamaduplicate', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses', $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses', $data); + + $response->assertStatus(302); + } + + public function testExpensePut() { $data = [ 'public_notes' => $this->faker->firstName, - 'id_number' => 'Coolio', + 'number' => 'Coolio', ]; $response = $this->withHeaders([ @@ -70,6 +93,22 @@ class ExpenseApiTest extends TestCase ])->put('/api/v1/expenses/'.$this->encodePrimaryKey($this->expense->id), $data); $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/expenses/'.$this->encodePrimaryKey($this->expense->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses/', $data); + + $response->assertStatus(302); + + } public function testExpenseGet() diff --git a/tests/Feature/InvoiceTest.php b/tests/Feature/InvoiceTest.php index 8ad15adfc832..68341e10b631 100644 --- a/tests/Feature/InvoiceTest.php +++ b/tests/Feature/InvoiceTest.php @@ -125,8 +125,15 @@ class InvoiceTest extends TestCase ])->post('/api/v1/invoices/', $invoice) ->assertStatus(200); - //test that the same request should produce a validation error due - //to duplicate number being used. + + $arr = $response->json(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/invoices/'.$arr['data']['id'], $invoice) + ->assertStatus(200); + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, diff --git a/tests/Feature/PaymentTest.php b/tests/Feature/PaymentTest.php index 74e89dbdc5a2..11a1387256af 100644 --- a/tests/Feature/PaymentTest.php +++ b/tests/Feature/PaymentTest.php @@ -104,6 +104,15 @@ class PaymentTest extends TestCase $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id), $Payment->toArray()); + + $response->assertStatus(200); + + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, diff --git a/tests/Feature/ProjectApiTest.php b/tests/Feature/ProjectApiTest.php index d843329482d7..a9062e742cab 100644 --- a/tests/Feature/ProjectApiTest.php +++ b/tests/Feature/ProjectApiTest.php @@ -16,6 +16,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Session; use Tests\MockAccountData; use Tests\TestCase; +use Illuminate\Validation\ValidationException; /** * @test @@ -56,6 +57,7 @@ class ProjectApiTest extends TestCase $data = [ 'name' => $this->faker->firstName, 'client_id' => $this->client->hashed_id, + 'number' => 'duplicate', ]; $response = $this->withHeaders([ @@ -64,6 +66,26 @@ class ProjectApiTest extends TestCase ])->post('/api/v1/projects', $data); $response->assertStatus(200); + + $arr = $response->json(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/projects/'.$arr['data']['id'], $data)->assertStatus(200); + + try{ + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/projects', $data); + } + catch(ValidationException $e){ + $response->assertStatus(302); + } + + + } public function testProjectPut() diff --git a/tests/Feature/QuoteTest.php b/tests/Feature/QuoteTest.php index a01e66bdca50..c452c57b19a2 100644 --- a/tests/Feature/QuoteTest.php +++ b/tests/Feature/QuoteTest.php @@ -86,7 +86,8 @@ class QuoteTest extends TestCase $quote_update = [ 'status_id' => Quote::STATUS_APPROVED, - // 'client_id' => $this->encodePrimaryKey($quote->client_id), + 'client_id' => $this->encodePrimaryKey($this->quote->client_id), + 'number' => 'Rando', ]; $this->assertNotNull($this->quote); @@ -98,6 +99,22 @@ class QuoteTest extends TestCase $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/quotes/'.$this->encodePrimaryKey($this->quote->id), $quote_update); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/quotes/', $quote_update); + + $response->assertStatus(302); + + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, diff --git a/tests/Feature/RecurringInvoiceTest.php b/tests/Feature/RecurringInvoiceTest.php index 47cbd5415223..ca2e84d439de 100644 --- a/tests/Feature/RecurringInvoiceTest.php +++ b/tests/Feature/RecurringInvoiceTest.php @@ -117,6 +117,7 @@ class RecurringInvoiceTest extends TestCase $RecurringInvoice_update = [ 'status_id' => RecurringInvoice::STATUS_DRAFT, 'client_id' => $this->encodePrimaryKey($RecurringInvoice->client_id), + 'number' => 'customnumber' ]; $this->assertNotNull($RecurringInvoice); @@ -127,6 +128,26 @@ class RecurringInvoiceTest extends TestCase ])->put('/api/v1/recurring_invoices/'.$this->encodePrimaryKey($RecurringInvoice->id), $RecurringInvoice_update) ->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals('customnumber', $arr['data']['number']); + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/recurring_invoices/'.$this->encodePrimaryKey($RecurringInvoice->id), $RecurringInvoice_update) + ->assertStatus(200); + + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/recurring_invoices/', $RecurringInvoice_update) + ->assertStatus(302); + + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, diff --git a/tests/Feature/TaskApiTest.php b/tests/Feature/TaskApiTest.php index e9d07ae477d7..e401ed05e4f4 100644 --- a/tests/Feature/TaskApiTest.php +++ b/tests/Feature/TaskApiTest.php @@ -14,6 +14,7 @@ use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Session; +use Illuminate\Validation\ValidationException; use Tests\MockAccountData; use Tests\TestCase; @@ -44,6 +45,7 @@ class TaskApiTest extends TestCase { $data = [ 'description' => $this->faker->firstName, + 'number' => 'taskynumber' ]; $response = $this->withHeaders([ @@ -54,6 +56,27 @@ class TaskApiTest extends TestCase $arr = $response->json(); $response->assertStatus(200); + $this->assertEquals('taskynumber', $arr['data']['number']); + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/tasks/'.$arr['data']['id'], $data); + + $response->assertStatus(200); + + try{ + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/tasks', $data); + + $arr = $response->json(); + }catch(ValidationException $e){ + $response->assertStatus(302); + } + $this->assertNotEmpty($arr['data']['number']); } diff --git a/tests/Feature/VendorApiTest.php b/tests/Feature/VendorApiTest.php index cd8983413200..d4288c8b5f3c 100644 --- a/tests/Feature/VendorApiTest.php +++ b/tests/Feature/VendorApiTest.php @@ -14,6 +14,7 @@ use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Session; +use Illuminate\Validation\ValidationException; use Tests\MockAccountData; use Tests\TestCase; @@ -59,6 +60,7 @@ class VendorApiTest extends TestCase $data = [ 'name' => $this->faker->firstName, 'id_number' => 'Coolio', + 'number' => 'wiggles' ]; $response = $this->withHeaders([ @@ -67,6 +69,33 @@ class VendorApiTest extends TestCase ])->put('/api/v1/vendors/'.$this->encodePrimaryKey($this->vendor->id), $data); $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('Coolio', $arr['data']['id_number']); + $this->assertEquals('wiggles', $arr['data']['number']); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/vendors/'.$this->encodePrimaryKey($this->vendor->id), $data); + + $response->assertStatus(200); + + + try{ + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/vendors/', $data); + + + }catch(ValidationException $e){ + + $response->assertStatus(302); + + } + } public function testVendorGet()