mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Enable client contact password to be set via API. (#3402)
* Tests for client contact passwords * test for client API * Client Tests for password quality * Final tests for client contact password
This commit is contained in:
parent
0f1c685bfa
commit
e2ed1fad8b
@ -42,6 +42,16 @@ class StoreClientRequest extends Request
|
|||||||
$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;
|
||||||
$rules['settings'] = new ValidClientGroupSettingsRule();
|
$rules['settings'] = new ValidClientGroupSettingsRule();
|
||||||
$rules['contacts.*.email'] = 'nullable|distinct';
|
$rules['contacts.*.email'] = 'nullable|distinct';
|
||||||
|
$rules['contacts.*.password'] = [
|
||||||
|
'sometimes',
|
||||||
|
'string',
|
||||||
|
'min:7', // must be at least 10 characters in length
|
||||||
|
'regex:/[a-z]/', // must contain at least one lowercase letter
|
||||||
|
'regex:/[A-Z]/', // must contain at least one uppercase letter
|
||||||
|
'regex:/[0-9]/', // must contain at least one digit
|
||||||
|
//'regex:/[@$!%*#?&.]/', // must contain a special character
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
// $contacts = request('contacts');
|
// $contacts = request('contacts');
|
||||||
|
|
||||||
@ -72,13 +82,25 @@ class StoreClientRequest extends Request
|
|||||||
{
|
{
|
||||||
foreach($input['contacts'] as $key => $contact)
|
foreach($input['contacts'] as $key => $contact)
|
||||||
{
|
{
|
||||||
if(is_numeric($contact['id']))
|
if(array_key_exists('id', $contact) && is_numeric($contact['id']))
|
||||||
unset($input['contacts'][$key]['id']);
|
unset($input['contacts'][$key]['id']);
|
||||||
elseif(is_string($contact['id']))
|
elseif(array_key_exists('id', $contact) && is_string($contact['id']))
|
||||||
$input['contacts'][$key]['id'] = $this->decodePrimaryKey($contact['id']);
|
$input['contacts'][$key]['id'] = $this->decodePrimaryKey($contact['id']);
|
||||||
|
|
||||||
|
|
||||||
|
//Filter the client contact password - if it is sent with ***** we should ignore it!
|
||||||
|
if(isset($contact['password']))
|
||||||
|
{
|
||||||
|
$contact['password'] = str_replace("*", "", $contact['password']);
|
||||||
|
|
||||||
|
if(strlen($contact['password']) == 0)
|
||||||
|
unset($input['contacts'][$key]['password']);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,15 +49,16 @@ class UpdateClientRequest extends Request
|
|||||||
$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;
|
||||||
$rules['settings'] = new ValidClientGroupSettingsRule();
|
$rules['settings'] = new ValidClientGroupSettingsRule();
|
||||||
$rules['contacts.*.email'] = 'nullable|distinct';
|
$rules['contacts.*.email'] = 'nullable|distinct';
|
||||||
|
$rules['contacts.*.password'] = [
|
||||||
|
'sometimes',
|
||||||
|
'string',
|
||||||
|
'min:7', // must be at least 10 characters in length
|
||||||
|
'regex:/[a-z]/', // must contain at least one lowercase letter
|
||||||
|
'regex:/[A-Z]/', // must contain at least one uppercase letter
|
||||||
|
'regex:/[0-9]/', // must contain at least one digit
|
||||||
|
//'regex:/[@$!%*#?&.]/', // must contain a special character
|
||||||
|
];
|
||||||
|
|
||||||
// $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;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,11 +84,20 @@ class UpdateClientRequest extends Request
|
|||||||
{
|
{
|
||||||
foreach($input['contacts'] as $key => $contact)
|
foreach($input['contacts'] as $key => $contact)
|
||||||
{
|
{
|
||||||
if(is_numeric($contact['id']))
|
if(array_key_exists('id', $contact) && is_numeric($contact['id']))
|
||||||
unset($input['contacts'][$key]['id']);
|
unset($input['contacts'][$key]['id']);
|
||||||
elseif(is_string($contact['id']))
|
elseif(array_key_exists('id', $contact) && is_string($contact['id']))
|
||||||
$input['contacts'][$key]['id'] = $this->decodePrimaryKey($contact['id']);
|
$input['contacts'][$key]['id'] = $this->decodePrimaryKey($contact['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Filter the client contact password - if it is sent with ***** we should ignore it!
|
||||||
|
if(isset($contact['password']))
|
||||||
|
{
|
||||||
|
$contact['password'] = str_replace("*", "", $contact['password']);
|
||||||
|
|
||||||
|
if(strlen($contact['password']) == 0)
|
||||||
|
unset($input['contacts'][$key]['password']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
|
@ -325,7 +325,7 @@ class Company extends BaseModel
|
|||||||
|
|
||||||
public function domain()
|
public function domain()
|
||||||
{
|
{
|
||||||
return 'https://' . $this->subdomain . config('ninja.app_domain');
|
return $this->subdomain . config('ninja.app_domain');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notification(Notification $notification)
|
public function notification(Notification $notification)
|
||||||
|
@ -105,6 +105,7 @@ class CompanyTransformer extends EntityTransformer
|
|||||||
'portal_domain' => (string) $company->portal_domain ?: '',
|
'portal_domain' => (string) $company->portal_domain ?: '',
|
||||||
'settings' => $company->settings ?: '',
|
'settings' => $company->settings ?: '',
|
||||||
'enabled_tax_rates' => (int)$company->enabled_tax_rates,
|
'enabled_tax_rates' => (int)$company->enabled_tax_rates,
|
||||||
|
'enabled_modules' => (int)$company->enabled_modules,
|
||||||
'updated_at' => (int)$company->updated_at,
|
'updated_at' => (int)$company->updated_at,
|
||||||
'archived_at' => (int)$company->deleted_at,
|
'archived_at' => (int)$company->deleted_at,
|
||||||
'created_at' =>(int)$company->created_at,
|
'created_at' =>(int)$company->created_at,
|
||||||
|
@ -7,6 +7,7 @@ use App\Models\Account;
|
|||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Models\CompanyToken;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Faker\Factory;
|
use Faker\Factory;
|
||||||
@ -17,6 +18,7 @@ use Illuminate\Foundation\Testing\WithFaker;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,6 +40,9 @@ class ClientTest extends TestCase
|
|||||||
|
|
||||||
Model::reguard();
|
Model::reguard();
|
||||||
|
|
||||||
|
$this->withoutExceptionHandling();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testClientList()
|
public function testClientList()
|
||||||
@ -266,6 +271,174 @@ class ClientTest extends TestCase
|
|||||||
$this->assertEquals($client->contacts->count(), 3);
|
$this->assertEquals($client->contacts->count(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testCreatingClientAndContacts()
|
||||||
|
{
|
||||||
|
|
||||||
|
$account = factory(\App\Models\Account::class)->create();
|
||||||
|
$company = factory(\App\Models\Company::class)->create([
|
||||||
|
'account_id' => $account->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$account->default_company_id = $company->id;
|
||||||
|
$account->save();
|
||||||
|
|
||||||
|
$user = factory(\App\Models\User::class)->create([
|
||||||
|
// 'account_id' => $account->id,
|
||||||
|
'confirmation_code' => $this->createDbHash(config('database.default'))
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user->companies()->attach($company->id, [
|
||||||
|
'account_id' => $account->id,
|
||||||
|
'is_owner' => 1,
|
||||||
|
'is_admin' => 1,
|
||||||
|
'permissions' => '',
|
||||||
|
'settings' => '',
|
||||||
|
'is_locked' => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$ct = CompanyToken::create([
|
||||||
|
'account_id' => $account->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'token' => \Illuminate\Support\Str::random(64),
|
||||||
|
'name' => $user->first_name. ' '. $user->last_name,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$token = $ct->token;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'A loyal Client',
|
||||||
|
'contacts' => [
|
||||||
|
['email' => $this->faker->unique()->safeEmail]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->post('/api/v1/clients/', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
// $arr = $response->json();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'A loyal Client',
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'email' => $this->faker->unique()->safeEmail,
|
||||||
|
'password' => '*****',
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->post('/api/v1/clients/', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'A loyal Client',
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'email' => $this->faker->unique()->safeEmail,
|
||||||
|
'password' => '1'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->post('/api/v1/clients/', $data);
|
||||||
|
}
|
||||||
|
catch(ValidationException $e) {
|
||||||
|
|
||||||
|
$message = json_decode($e->validator->getMessageBag(),1);
|
||||||
|
\Log::error($message);
|
||||||
|
$this->assertNotNull($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'A loyal Client',
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'email' => $this->faker->unique()->safeEmail,
|
||||||
|
'password' => '1Qajsj...33'
|
||||||
|
],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->post('/api/v1/clients/', $data);
|
||||||
|
}
|
||||||
|
catch(ValidationException $e) {
|
||||||
|
|
||||||
|
$message = json_decode($e->validator->getMessageBag(),1);
|
||||||
|
//\Log::error($message);
|
||||||
|
//$this->assertNotNull($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'A loyal Client',
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'email' => $this->faker->unique()->safeEmail,
|
||||||
|
'password' => '1Qajsj...33'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'email' => $this->faker->unique()->safeEmail,
|
||||||
|
'password' => '1234AAAAAaaaaa'
|
||||||
|
],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->post('/api/v1/clients/', $data);
|
||||||
|
}
|
||||||
|
catch(ValidationException $e) {
|
||||||
|
|
||||||
|
$message = json_decode($e->validator->getMessageBag(),1);
|
||||||
|
\Log::error($message);
|
||||||
|
$this->assertNotNull($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
|
||||||
|
|
||||||
|
$arr = $response->json();
|
||||||
|
|
||||||
|
$client_id = $arr['data']['id'];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->put('/api/v1/clients/' . $client_id, $data)->assertStatus(200);
|
||||||
|
|
||||||
|
$arr = $response->json();
|
||||||
|
|
||||||
|
\Log::error($arr);
|
||||||
|
|
||||||
|
}
|
||||||
/** @test */
|
/** @test */
|
||||||
// public function testMassivelyCreatingClients()
|
// public function testMassivelyCreatingClients()
|
||||||
// {
|
// {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user