1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-16 16:13:20 +01:00

Merge pull request #5979 from turbo124/v5-stable

v5.1.74
This commit is contained in:
David Bomba 2021-06-09 15:35:04 +10:00 committed by GitHub
commit 3da09e0e23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 243 additions and 27 deletions

View File

@ -1 +1 @@
5.1.72 5.1.74

View File

@ -0,0 +1,166 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Console\Commands;
use App;
use App\Factory\ClientContactFactory;
use App\Models\Account;
use App\Models\Activity;
use App\Models\Backup;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\ClientGatewayToken;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\CompanyLedger;
use App\Models\CompanyToken;
use App\Models\CompanyUser;
use App\Models\Contact;
use App\Models\Credit;
use App\Models\CreditInvitation;
use App\Models\Design;
use App\Models\Document;
use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Models\Gateway;
use App\Models\GroupSetting;
use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\Paymentable;
use App\Models\Product;
use App\Models\Project;
use App\Models\Quote;
use App\Models\QuoteInvitation;
use App\Models\RecurringInvoice;
use App\Models\RecurringInvoiceInvitation;
use App\Models\Subscription;
use App\Models\SystemLog;
use App\Models\Task;
use App\Models\TaskStatus;
use App\Models\TaxRate;
use App\Models\User;
use App\Models\Vendor;
use App\Models\VendorContact;
use App\Models\Webhook;
use App\Utils\Ninja;
use DB;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Mail;
use Symfony\Component\Console\Input\InputOption;
/**
* Class CheckDb.
*/
class CheckDb extends Command
{
/**
* @var string
*/
protected $signature = 'ninja:check-db';
/**
* @var string
*/
protected $description = 'Check MultiDB';
protected $log = '';
private $entities = [
Account::class,
Activity::class,
Backup::class,
Client::class,
ClientContact::class,
ClientGatewayToken::class,
Company::class,
CompanyGateway::class,
CompanyLedger::class,
CompanyToken::class,
CompanyUser::class,
Credit::class,
CreditInvitation::class,
Design::class,
Document::class,
Expense::class,
ExpenseCategory::class,
Gateway::class,
GroupSetting::class,
Invoice::class,
InvoiceInvitation::class,
Payment::class,
Paymentable::class,
PaymentHash::class,
Product::class,
Project::class,
Quote::class,
QuoteInvitation::class,
RecurringInvoice::class,
RecurringInvoiceInvitation::class,
Subscription::class,
SystemLog::class,
Task::class,
TaskStatus::class,
TaxRate::class,
User::class,
Vendor::class,
VendorContact::class,
WebHook::class,
];
public function handle()
{
foreach($this->entities as $entity) {
$this->LogMessage("V5_DB1");
$count_db_1 = $entity::on('db-ninja-01')->count();
$count_db_2 = $entity::on('db-ninja-02a')->count();
$diff = $count_db_1 - $count_db_2;
if($diff != 0)
$this->logMessage("{$entity} DB1: {$count_db_1} - DB2: {$count_db_2} - diff = {$diff}");
}
foreach($this->entities as $entity) {
$this->LogMessage("V5_DB2");
$count_db_1 = $entity::on('db-ninja-02')->count();
$count_db_2 = $entity::on('db-ninja-01a')->count();
$diff = $count_db_1 - $count_db_2;
if($diff != 0)
$this->logMessage("{$entity} DB1: {$count_db_1} - DB2: {$count_db_2} - diff = {$diff}");
}
}
private function logMessage($str)
{
$str = date('Y-m-d h:i:s').' '.$str;
$this->info($str);
$this->log .= $str."\n";
}
}

View File

@ -75,7 +75,7 @@ class Kernel extends ConsoleKernel
} }
if(config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled')) { if(config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && !config('ninja.is_docker')) {
$schedule->command('queue:work')->everyMinute()->withoutOverlapping(); $schedule->command('queue:work')->everyMinute()->withoutOverlapping();
$schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping(); $schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping();

View File

@ -93,6 +93,10 @@ class CompanyImport implements ShouldQueue
public $pre_flight_checks_pass = true; public $pre_flight_checks_pass = true;
public $force_user_coalesce = false;
public $company_owner;
private $importables = [ private $importables = [
// 'company', // 'company',
'users', 'users',
@ -141,6 +145,7 @@ class CompanyImport implements ShouldQueue
public function __construct(Company $company, User $user, string $hash, array $request_array) public function __construct(Company $company, User $user, string $hash, array $request_array)
{ {
$this->company = $company; $this->company = $company;
$this->user = $user;
$this->hash = $hash; $this->hash = $hash;
$this->request_array = $request_array; $this->request_array = $request_array;
$this->current_app_version = config('ninja.app_version'); $this->current_app_version = config('ninja.app_version');
@ -152,6 +157,7 @@ class CompanyImport implements ShouldQueue
$this->company = Company::where('company_key', $this->company->company_key)->firstOrFail(); $this->company = Company::where('company_key', $this->company->company_key)->firstOrFail();
$this->account = $this->company->account; $this->account = $this->company->account;
$this->company_owner = $this->company->owner();
nlog("Company ID = {$this->company->id}"); nlog("Company ID = {$this->company->id}");
nlog("Hash ID = {$this->hash}"); nlog("Hash ID = {$this->hash}");
@ -164,17 +170,18 @@ class CompanyImport implements ShouldQueue
$this->backup_file = json_decode(base64_decode($this->backup_file)); $this->backup_file = json_decode(base64_decode($this->backup_file));
// nlog($this->backup_file); // nlog($this->backup_file);
$this->checkUserCount();
if(array_key_exists('import_settings', $this->request_array) && $this->request_array['import_settings'] == 'true') { if(array_key_exists('import_settings', $this->request_array) && $this->request_array['import_settings'] == 'true') {
$this->checkUserCount()->preFlightChecks()->importSettings();
$this->preFlightChecks()->importSettings();
} }
if(array_key_exists('import_data', $this->request_array) && $this->request_array['import_data'] == 'true') { if(array_key_exists('import_data', $this->request_array) && $this->request_array['import_data'] == 'true') {
try{ try{
$this->checkUserCount() $this->preFlightChecks()
->preFlightChecks()
->purgeCompanyData() ->purgeCompanyData()
->importData(); ->importData();
@ -206,23 +213,21 @@ class CompanyImport implements ShouldQueue
$company_users = $this->company->users; $company_users = $this->company->users;
$company_owner = $this->company->owner();
if($this->company->account->isFreeHostedClient()){
nlog("This is a free account"); nlog("This is a free account");
nlog("Backup user count = ".count($backup_users)); nlog("Backup user count = ".count($backup_users));
if(count($backup_users) > 1){ if(count($backup_users) > 1){
$this->message = 'Only one user can be in the import for a Free Account'; // $this->message = 'Only one user can be in the import for a Free Account';
$this->pre_flight_checks_pass = false; // $this->pre_flight_checks_pass = false;
$this->force_user_coalesce = true;
} }
nlog("backup users email = " . $backup_users[0]->email); nlog("backup users email = " . $backup_users[0]->email);
if(count($backup_users) == 1 && $company_owner->email != $backup_users[0]->email) { if(count($backup_users) == 1 && $this->company_owner->email != $backup_users[0]->email) {
$this->message = 'Account emails do not match. Account owner email must match backup user email'; // $this->message = 'Account emails do not match. Account owner email must match backup user email';
$this->pre_flight_checks_pass = false; // $this->pre_flight_checks_pass = false;
$this->force_user_coalesce = true;
} }
$backup_users_emails = array_column($backup_users, 'email'); $backup_users_emails = array_column($backup_users, 'email');
@ -236,8 +241,9 @@ class CompanyImport implements ShouldQueue
if($existing_user_count > 1){ if($existing_user_count > 1){
if($this->account->plan == 'pro'){ if($this->account->plan == 'pro'){
$this->message = 'Pro plan is limited to one user, you have multiple users in the backup file'; // $this->message = 'Pro plan is limited to one user, you have multiple users in the backup file';
$this->pre_flight_checks_pass = false; // $this->pre_flight_checks_pass = false;
$this->force_user_coalesce = true;
} }
if($this->account->plan == 'enterprise'){ if($this->account->plan == 'enterprise'){
@ -268,11 +274,6 @@ class CompanyImport implements ShouldQueue
} }
}
nlog($this->message);
nlog($this->pre_flight_checks_pass);
return $this; return $this;
} }
@ -1217,11 +1218,22 @@ class CompanyImport implements ShouldQueue
return implode(",", $tmp_arr); return implode(",", $tmp_arr);
} }
/* Transform all IDs from old to new
*
* In the case of users - we need to check if the system
* is attempting to migrate resources above their quota,
*
* ie. > 50 clients or more than 1 user
*/
private function transformId(string $resource, ?string $old): ?int private function transformId(string $resource, ?string $old): ?int
{ {
if(empty($old)) if(empty($old))
return null; return null;
if ($resource == 'users' && $this->force_user_coalesce){
return $this->company_owner->id;
}
if (! array_key_exists($resource, $this->ids)) { if (! array_key_exists($resource, $this->ids)) {
// nlog($this->ids); // nlog($this->ids);
throw new \Exception("Resource {$resource} not available."); throw new \Exception("Resource {$resource} not available.");

View File

@ -212,7 +212,7 @@ class Import implements ShouldQueue
} }
// if(Ninja::isHosted() && array_key_exists('ninja_tokens', $data)) // if(Ninja::isHosted() && array_key_exists('ninja_tokens', $data))
// $this->processNinjaTokens($data['ninja_tokens']); $this->processNinjaTokens($data['ninja_tokens']);
$this->setInitialCompanyLedgerBalances(); $this->setInitialCompanyLedgerBalances();
@ -1659,8 +1659,10 @@ class Import implements ShouldQueue
private function processNinjaTokens(array $data) private function processNinjaTokens(array $data)
{ {
nlog("attempting to process Ninja Tokens");
if(Ninja::isHosted()) if(Ninja::isHosted())
\Modules\Admin\Jobs\Account\NinjaUser::dispatch($data, $this->company); \Modules\Admin\Jobs\Account\NinjaUser::dispatchNow($data, $this->company);
} }

View File

@ -98,7 +98,7 @@ class PayPalExpressPaymentDriver extends BaseDriver
$message = [ $message = [
'server_response' => $response->getMessage(), 'server_response' => $response->getMessage(),
'data' => $this->checkout->payment_hash->data, 'data' => $this->payment_hash->data,
]; ];
SystemLogger::dispatch( SystemLogger::dispatch(

View File

@ -630,7 +630,7 @@ class SubscriptionService
*/ */
public function triggerWebhook($context) public function triggerWebhook($context)
{ {
if (empty($this->subscription->webhook_configuration['post_purchase_url']) || empty($this->subscription->webhook_configuration['post_purchase_rest_method'])) { if (empty($this->subscription->webhook_configuration['post_purchase_url']) || is_null($this->subscription->webhook_configuration['post_purchase_url']) || strlen($this->subscription->webhook_configuration['post_purchase_url']) < 1) {
return ["message" => "Success", "status_code" => 200]; return ["message" => "Success", "status_code" => 200];
} }

View File

@ -99,6 +99,24 @@ return [
// ), // ),
], ],
'db-ninja-01a' => [
'driver' => 'mysql',
'host' => env('DB_HOST1', env('DB_HOST', '127.0.0.1')),
'database' => env('DB_DATABASE2', env('DB_DATABASE', 'forge')),
'username' => env('DB_USERNAME2', env('DB_USERNAME', 'forge')),
'password' => env('DB_PASSWORD2', env('DB_PASSWORD', '')),
'port' => env('DB_PORT1', env('DB_PORT', '3306')),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => env('DB_STRICT', false),
'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8',
// 'options' => array(
// PDO::ATTR_EMULATE_PREPARES => true
// ),
],
'db-ninja-02' => [ 'db-ninja-02' => [
'driver' => 'mysql', 'driver' => 'mysql',
'host' => env('DB_HOST2', env('DB_HOST', '127.0.0.1')), 'host' => env('DB_HOST2', env('DB_HOST', '127.0.0.1')),
@ -116,6 +134,24 @@ return [
// PDO::ATTR_EMULATE_PREPARES => true // PDO::ATTR_EMULATE_PREPARES => true
// ), // ),
], ],
'db-ninja-02a' => [
'driver' => 'mysql',
'host' => env('DB_HOST2', env('DB_HOST', '127.0.0.1')),
'database' => env('DB_DATABASE1', env('DB_DATABASE', 'forge')),
'username' => env('DB_USERNAME1', env('DB_USERNAME', 'forge')),
'password' => env('DB_PASSWORD1', env('DB_PASSWORD', '')),
'port' => env('DB_PORT2', env('DB_PORT', '3306')),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => env('DB_STRICT', false),
'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8',
// 'options' => array(
// PDO::ATTR_EMULATE_PREPARES => true
// ),
],
], ],
/* /*

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.1.72', 'app_version' => '5.1.74',
'app_tag' => '5.1.72-release', 'app_tag' => '5.1.74-release',
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''), 'api_secret' => env('API_SECRET', ''),