1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 21:22:58 +01:00

Merge pull request #8261 from turbo124/v5-develop

Fixes for webhooks
This commit is contained in:
David Bomba 2023-02-08 23:43:58 +11:00 committed by GitHub
commit 3e1b983955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 349 additions and 79 deletions

View File

@ -834,7 +834,6 @@ class CompanySettings extends BaseSettings
'$client.address1',
'$client.address2',
'$client.city_state_postal',
'$client.postal_city',
'$client.country',
'$client.phone',
'$contact.email',
@ -846,7 +845,6 @@ class CompanySettings extends BaseSettings
'$vendor.address1',
'$vendor.address2',
'$vendor.city_state_postal',
'$vendor.postal_city',
'$vendor.country',
'$vendor.phone',
'$contact.email',
@ -871,7 +869,6 @@ class CompanySettings extends BaseSettings
'$company.address1',
'$company.address2',
'$company.city_state_postal',
'$company.postal_city',
'$company.country',
],
'invoice_details' => [

View File

@ -195,4 +195,56 @@ class Request extends FormRequest
public function prepareForValidation()
{
}
public function checkTimeLog(array $log): bool
{
if(count($log) == 0)
return true;
/*Get first value of all arrays*/
$result = array_column($log, 0);
/*Sort the array in ascending order*/
asort($result);
$new_array = [];
/*Rebuild the array in order*/
foreach($result as $key => $value)
$new_array[] = $log[$key];
/*Iterate through the array and perform checks*/
foreach($new_array as $key => $array)
{
/*Flag which helps us know if there is a NEXT timelog*/
$next = false;
/* If there are more than 1 time log in the array, ensure the last timestamp is not zero*/
if(count($new_array) >1 && $array[1] == 0)
return false;
/* Check if the start time is greater than the end time */
/* Ignore the last value for now, we'll do a separate check for this */
if($array[0] > $array[1] && $array[1] != 0)
return false;
/* Find the next time log value - if it exists */
if(array_key_exists($key+1, $new_array))
$next = $new_array[$key+1];
/* check the next time log and ensure the start time is GREATER than the end time of the previous record */
if($next && $next[0] < $array[1])
return false;
/* Get the last row of the timelog*/
$last_row = end($new_array);
/*If the last value is NOT zero, ensure start time is not GREATER than the endtime */
if($last_row[1] != 0 && $last_row[0] > $last_row[1])
return false;
return true;
}
}
}

View File

@ -53,6 +53,9 @@ class StoreTaskRequest extends Request
$fail('The '.$attribute.' - '.print_r($k,1).' is invalid. Unix timestamps only.');
}
if(!$this->checkTimeLog($values))
$fail('Please correct overlapping values');
}];

View File

@ -59,6 +59,9 @@ class UpdateTaskRequest extends Request
$fail('The '.$attribute.' - '.print_r($k,1).' is invalid. Unix timestamps only.');
}
if(!$this->checkTimeLog($values))
$fail('Please correct overlapping values');
}];
return $this->globalRules($rules);

View File

@ -39,6 +39,8 @@ class StoreWebhookRequest extends Request
{
$input = $this->all();
if(!isset($input['rest_method']))
$input['rest_method'] = 'post';
// if(isset($input['headers']) && count($input['headers']) == 0)
// $input['headers'] = null;

View File

@ -44,6 +44,9 @@ class UpdateWebhookRequest extends Request
{
$input = $this->all();
if(!isset($input['rest_method']))
$input['rest_method'] = 'post';
// if(isset($input['headers']) && count($input['headers']) == 0)
// $input['headers'] = null;

View File

@ -18,7 +18,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class BankTransactionRule extends BaseModel
{
use SoftDeletes;
use MakesHash;
use Filterable;
protected $fillable = [
@ -66,6 +65,37 @@ class BankTransactionRule extends BaseModel
private array $search_results = [];
public function getEntityType()
{
return self::class;
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
public function client()
{
return $this->belongsTo(Client::class);
}
public function user()
{
return $this->belongsTo(User::class)->withTrashed();
}
public function expense_category()
{
return $this->belongsTo(ExpenseCategory::class, 'category_id')->withTrashed();
}
// rule object looks like this:
//[
// {
@ -138,34 +168,5 @@ class BankTransactionRule extends BaseModel
// }
// }
public function getEntityType()
{
return self::class;
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
public function client()
{
return $this->belongsTo(Client::class);
}
public function user()
{
return $this->belongsTo(User::class)->withTrashed();
}
public function expense_category()
{
return $this->belongsTo(ExpenseCategory::class, 'category_id', 'id')->withTrashed();
}
}

View File

@ -206,12 +206,22 @@ class BaseModel extends Model
return ctrans('texts.item');
}
public function sendEvent($event_id, $additional_data=""){
/**
* Model helper to send events for webhooks
*
* @param int $event_id
* @param string $additional_data optional includes
*
* @return void
*/
public function sendEvent(int $event_id, string $additional_data = ""): void
{
$subscriptions = Webhook::where('company_id', $this->company_id)
->where('event_id', $event_id)
->exists();
->where('event_id', $event_id)
->exists();
if ($subscriptions) {
WebhookHandler::dispatch($event_id, $this, $this->company, $additional_data)->delay(0);
WebhookHandler::dispatch($event_id, $this, $this->company, $additional_data);
}
}

View File

@ -59,7 +59,7 @@ class ClientObserver
->exists();
if ($subscriptions)
WebhookHandler::dispatch($event, $client, $client->company)->delay(0);
WebhookHandler::dispatch($event, $client, $client->company, 'client')->delay(0);
}

View File

@ -58,7 +58,7 @@ class InvoiceObserver
->exists();
if ($subscriptions)
WebhookHandler::dispatch($event, $invoice, $invoice->company)->delay(0);
WebhookHandler::dispatch($event, $invoice, $invoice->company, 'client')->delay(0);
}
/**

View File

@ -13,10 +13,13 @@ namespace App\Transformers;
use App\Models\BankTransaction;
use App\Models\BankTransactionRule;
use App\Models\Client;
use App\Models\Company;
use App\Models\ExpenseCategory;
use App\Transformers\VendorTransformer;
use App\Models\Vendor;
use App\Transformers\ExpenseCategoryTransformer;
use App\Transformers\ExpenseCateogryTransformer;
use App\Transformers\VendorTransformer;
use App\Utils\Traits\MakesHash;
/**
@ -74,31 +77,34 @@ class BankTransactionRuleTransformer extends EntityTransformer
public function includeClient(BankTransactionRule $bank_transaction_rule)
{
$transformer = new ClientTransformer($this->serializer);
if(!$bank_transaction_rule->client)
return null;
return $this->includeItem($bank_transaction_rule->expense, $transformer, Client::class);
$transformer = new ClientTransformer($this->serializer);
return $this->includeItem($bank_transaction_rule->client, $transformer, Client::class);
}
public function includeVendor(BankTransactionRule $bank_transaction_rule)
{
$transformer = new VendorTransformer($this->serializer);
if(!$bank_transaction_rule->vendor)
return null;
$transformer = new VendorTransformer($this->serializer);
return $this->includeItem($bank_transaction_rule->vendor, $transformer, Vendor::class);
}
public function includeExpenseCategory(BankTransactionRule $bank_transaction_rule)
{
$transformer = new ExpenseCategoryTransformer($this->serializer);
if(!$bank_transaction_rule->expense_cateogry)
if(!$bank_transaction_rule->expense_category)
return null;
$transformer = new ExpenseCategoryTransformer($this->serializer);
return $this->includeItem($bank_transaction_rule->expense_category, $transformer, ExpenseCategory::class);
}

View File

@ -223,15 +223,15 @@ class Number
/* 08-01-2022 allow increased precision for unit price*/
$v = rtrim(sprintf('%f', $value), '0');
// $precision = strlen(substr(strrchr($v, $decimal), 1));
if ($v < 1) {
/* 08-02-2023 special if block to render $0.5 to $0.50*/
if ($v < 1 && strlen($v) == 3) {
$precision = 2;
}
elseif ($v < 1) {
$precision = strlen($v) - strrpos($v, '.') - 1;
}
// if($precision == 1)
// $precision = 2;
$value = number_format($v, $precision, $decimal, $thousand);
$symbol = $currency->symbol;

View File

@ -185,7 +185,7 @@ class BankTransactionRuleTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/bank_transaction_rules/'. $br->hashed_id, $data);
])->putJson('/api/v1/bank_transaction_rules/'. $br->hashed_id. '?include=expense_category', $data);
} catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1);
@ -194,7 +194,7 @@ class BankTransactionRuleTest extends TestCase
if($response){
$arr = $response->json();
nlog($arr);
$response->assertStatus(200);
}

View File

@ -43,6 +43,198 @@ class TaskApiTest extends TestCase
Model::reguard();
}
private function checkTimeLog(array $log): bool
{
if(count($log) == 0)
return true;
/*Get first value of all arrays*/
$result = array_column($log, 0);
/*Sort the array in ascending order*/
asort($result);
$new_array = [];
/*Rebuild the array in order*/
foreach($result as $key => $value)
$new_array[] = $log[$key];
/*Iterate through the array and perform checks*/
foreach($new_array as $key => $array)
{
/*Flag which helps us know if there is a NEXT timelog*/
$next = false;
/* If there are more than 1 time log in the array, ensure the last timestamp is not zero*/
if(count($new_array) >1 && $array[1] == 0)
return false;
/* Check if the start time is greater than the end time */
/* Ignore the last value for now, we'll do a separate check for this */
if($array[0] > $array[1] && $array[1] != 0)
return false;
/* Find the next time log value - if it exists */
if(array_key_exists($key+1, $new_array))
$next = $new_array[$key+1];
/* check the next time log and ensure the start time is GREATER than the end time of the previous record */
if($next && $next[0] < $array[1])
return false;
/* Get the last row of the timelog*/
$last_row = end($new_array);
/*If the last value is NOT zero, ensure start time is not GREATER than the endtime */
if($last_row[1] != 0 && $last_row[0] > $last_row[1])
return false;
return true;
}
}
public function testTimeLogChecker1()
{
$log = [
[50,0]
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker2()
{
$log = [
[4,5],
[5,1]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker3()
{
$log = [
[4,5],
[3,50]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker4()
{
$log = [
[4,5],
[3,0]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker5()
{
$log = [
[4,5],
[3,1]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker6()
{
$log = [
[4,5],
[1,3],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker7()
{
$log = [
[1,3],
[4,5]
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker8()
{
$log = [
[1,3],
[50,0]
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker9()
{
$log = [
[4,5,'bb'],
[50,0,'aa'],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker10()
{
$log = [
[4,5,'5'],
[50,0,'3'],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker11()
{
$log = [
[1,2,'a'],
[3,4,'d'],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTaskListClientStatus()

View File

@ -49,33 +49,6 @@ class WebhookAPITest extends TestCase
$this->withoutExceptionHandling();
}
// public function testClientWebhooks()
// {
// // client archived = 37
// $data = [
// 'target_url' => 'http://hook.com',
// 'event_id' => 37,
// 'rest_method' => 'post',
// 'format' => 'JSON',
// ];
// $response = $this->withHeaders([
// 'X-API-SECRET' => config('ninja.api_secret'),
// 'X-API-TOKEN' => $this->token,
// ])->post('/api/v1/webhooks', $data);
// $repo = new ClientRepository(new ClientContactRepository());
// $repo->archive($this->client);
// \Illuminate\Support\Facades\Queue::after(function (WebhookHandler $event) {
// $this->assertTrue($event->job->isReleased());
// });
// \Illuminate\Support\Facades\Queue::assertPushed(WebhookHandler::class);
// }
public function testWebhookGetFilter()
{
$response = $this->withHeaders([
@ -98,6 +71,20 @@ class WebhookAPITest extends TestCase
public function testWebhookPostRoute()
{
$data = [
'target_url' => 'http://hook.com',
'event_id' => 1,
'format' => 'JSON',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/webhooks', $data);
$response->assertStatus(200);
$data = [
'target_url' => 'http://hook.com',
'event_id' => 1,
@ -116,6 +103,20 @@ class WebhookAPITest extends TestCase
$this->assertEquals(1, $arr['data']['event_id']);
$data = [
'target_url' => 'http://hook.com',
'event_id' => 2,
'format' => 'JSON',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/webhooks/'.$arr['data']['id'], $data);
$response->assertStatus(200);
$data = [
'target_url' => 'http://hook.com',
'event_id' => 2,