diff --git a/VERSION.txt b/VERSION.txt index b956517f3f..890743bb55 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.11.79 \ No newline at end of file +5.11.80 \ No newline at end of file diff --git a/app/Console/Commands/S3Cleanup.php b/app/Console/Commands/S3Cleanup.php index 6578b96aa9..93140682f0 100644 --- a/app/Console/Commands/S3Cleanup.php +++ b/app/Console/Commands/S3Cleanup.php @@ -57,8 +57,9 @@ class S3Cleanup extends Command $c1 = Company::on('db-ninja-01')->pluck('company_key'); $c2 = Company::on('db-ninja-02')->pluck('company_key'); + $c3 = Company::on('db-ninja-03')->pluck('company_key'); - $merged = $c1->merge($c2)->toArray(); + $merged = $c1->merge($c2)->merge($c3)->toArray(); $directories = Storage::disk(config('filesystems.default'))->directories(); diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php index 02135e6e12..b3222582d5 100644 --- a/app/Export/CSV/InvoiceItemExport.php +++ b/app/Export/CSV/InvoiceItemExport.php @@ -172,8 +172,7 @@ class InvoiceItemExport extends BaseExport $tmp_key = str_replace("item.", "", $key); if ($tmp_key == 'tax_id') { - // $tmp_key = 'tax_category'; - $item_array[$key] = $this->getTaxCategoryName((int)$item->tax_id); + $item_array[$key] = $this->getTaxCategoryName((int)$item->tax_id ?? 1); // @phpstan-ignore-line } elseif (property_exists($item, $tmp_key)) { $item_array[$key] = $item->{$tmp_key}; diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 4165544d43..465a8efb93 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -296,6 +296,20 @@ class InvoiceFilters extends QueryFilters return $this->builder->orderByRaw("REGEXP_REPLACE(invoices.number,'[^0-9]+','')+0 " . $dir); } + if ($sort_col[0] == 'status_id') { + // Special handling for status_id==2 (STATUS_SENT) with sub-statuses + return $this->builder->orderByRaw(" + CASE + WHEN status_id != 2 THEN status_id + WHEN status_id = 2 AND (due_date IS NOT NULL AND (due_date < NOW() OR partial_due_date < NOW())) THEN 2.9 + WHEN status_id = 2 AND last_viewed IS NOT NULL THEN 2.5 + WHEN status_id = 2 THEN 2.2 + ELSE status_id + END " . $dir); + + } + + return $this->builder->orderBy("{$this->builder->getQuery()->from}.".$sort_col[0], $dir); } diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index a220c49054..993e733175 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -104,7 +104,7 @@ class AccountController extends BaseController $cu = CompanyUser::query()->where('user_id', $account->users()->first()->id); $company_user = $cu->first(); - + $truth = app()->make(TruthSource::class); $truth->setCompanyUser($company_user); $truth->setUser($company_user->user); diff --git a/app/Http/Controllers/Auth/ContactResetPasswordController.php b/app/Http/Controllers/Auth/ContactResetPasswordController.php index 8f26037733..c54a90a4c7 100644 --- a/app/Http/Controllers/Auth/ContactResetPasswordController.php +++ b/app/Http/Controllers/Auth/ContactResetPasswordController.php @@ -122,7 +122,7 @@ class ContactResetPasswordController extends Controller event(new PasswordReset($user)); - auth()->login($user, true); + auth()->login($user, false); $response = Password::PASSWORD_RESET; diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index e613e6e4d2..73fc405581 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -280,7 +280,7 @@ class LoginController extends BaseController return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400); } - Auth::login($existing_user, true); + Auth::login($existing_user, false); /** @var \App\Models\CompanyUser $cu */ $cu = $this->hydrateCompanyUser(); @@ -301,7 +301,7 @@ class LoginController extends BaseController return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400); } - Auth::login($existing_login_user, true); + Auth::login($existing_login_user, false); /** @var \App\Models\User $user */ $user = auth()->user(); @@ -352,7 +352,7 @@ class LoginController extends BaseController $account = (new CreateAccount($new_account, request()->getClientIp()))->handle(); - Auth::login($account->default_company->owner(), true); + Auth::login($account->default_company->owner(), false); /** @var \App\Models\User $user */ $user = auth()->user(); @@ -456,17 +456,6 @@ class LoginController extends BaseController return response()->json(['message' => 'User exists, but never authenticated with OAuth, please use your email and password to login.'], 400); } - // If this is a result user/email combo - lets add their OAuth details details - // if ($email && $existing_login_user = MultiDB::hasUser(['email' => $email, 'oauth_provider_id' => 'microsoft'])) { - // if (!$existing_login_user->account) { - // return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400); - // } - - // Auth::login($existing_login_user, true); - - // return $this->existingLoginUser($user->getId(), 'microsoft'); - // } - // Signup! if (request()->has('create') && request()->input('create') == 'true') { $new_account = [ @@ -496,7 +485,7 @@ class LoginController extends BaseController */ private function existingOauthUser($existing_user) { - Auth::login($existing_user, true); + Auth::login($existing_user, false); /** @var \App\Models\CompanyUser $cu */ $cu = $this->hydrateCompanyUser(); @@ -569,17 +558,7 @@ class LoginController extends BaseController return response()->json(['message' => 'Please use your email and password to login.'], 400); } - // 2025-05-19 - this caused an issue when a user/email password combo user used their google account to login, it raced through and attempted to create a new account. - //If this is a result user/email combo - lets add their OAuth details details - // if ($existing_login_user = MultiDB::hasUser(['email' => $google->harvestEmail($user), 'oauth_provider_id' => 'google'])) { - // if (!$existing_login_user->account) { - // return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400); - // } - // Auth::login($existing_login_user, true); - - // return $this->existingLoginUser($google->harvestSubField($user), 'google'); - // } } if ($user) { @@ -589,7 +568,7 @@ class LoginController extends BaseController return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400); } - Auth::login($existing_login_user, true); + Auth::login($existing_login_user, false); return $this->existingLoginUser($google->harvestSubField($user), 'google'); } @@ -628,7 +607,7 @@ class LoginController extends BaseController return $account; } - Auth::login($account->default_company->owner(), true); + Auth::login($account->default_company->owner(), false); /** @var \App\Models\User $user */ $user = auth()->user(); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 74c33c014a..27dc42bdd2 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -12,51 +12,52 @@ namespace App\Http; -use App\Http\Middleware\ApiSecretCheck; +use App\Http\Middleware\Cors; +use App\Http\Middleware\SetDb; +use App\Http\Middleware\Locale; +use App\Http\Middleware\SetWebDb; +use App\Http\Middleware\UrlSetDb; +use App\Http\Middleware\TokenAuth; +use App\Http\Middleware\SetEmailDb; +use App\Http\Middleware\VerifyHash; +use App\Http\Middleware\SetInviteDb; +use App\Http\Middleware\TrimStrings; use App\Http\Middleware\Authenticate; -use App\Http\Middleware\CheckClientExistence; -use App\Http\Middleware\CheckForMaintenanceMode; -use App\Http\Middleware\ClientPortalEnabled; +use App\Http\Middleware\ContactSetDb; +use App\Http\Middleware\QueryLogging; +use App\Http\Middleware\TrustProxies; +use App\Http\Middleware\UserVerified; +use App\Http\Middleware\VendorLocale; +use App\Http\Middleware\PhantomSecret; +use App\Http\Middleware\SetDocumentDb; +use App\Http\Middleware\ApiSecretCheck; use App\Http\Middleware\ContactAccount; +use App\Http\Middleware\EncryptCookies; +use App\Http\Middleware\SessionDomains; use App\Http\Middleware\ContactKeyLogin; use App\Http\Middleware\ContactRegister; -use App\Http\Middleware\ContactSetDb; -use App\Http\Middleware\ContactTokenAuth; -use App\Http\Middleware\Cors; -use App\Http\Middleware\EncryptCookies; -use App\Http\Middleware\Locale; -use App\Http\Middleware\PasswordProtection; -use App\Http\Middleware\PhantomSecret; -use App\Http\Middleware\QueryLogging; -use App\Http\Middleware\RedirectIfAuthenticated; -use App\Http\Middleware\SessionDomains; -use App\Http\Middleware\SetDbByCompanyKey; -use App\Http\Middleware\SetDocumentDb; use App\Http\Middleware\SetDomainNameDb; -use App\Http\Middleware\SetEmailDb; -use App\Http\Middleware\SetInviteDb; -use App\Http\Middleware\SetWebDb; -use App\Http\Middleware\TokenAuth; -use App\Http\Middleware\TrimStrings; -use App\Http\Middleware\TrustProxies; -use App\Http\Middleware\UrlSetDb; -use App\Http\Middleware\UserVerified; -use App\Http\Middleware\ValidateSignature; -use App\Http\Middleware\VendorContactKeyLogin; -use App\Http\Middleware\VendorLocale; use App\Http\Middleware\VerifyCsrfToken; -use App\Http\Middleware\VerifyHash; -use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; +use App\Http\Middleware\ContactTokenAuth; use Illuminate\Auth\Middleware\Authorize; -use Illuminate\Auth\Middleware\EnsureEmailIsVerified; -use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; -use Illuminate\Foundation\Http\Kernel as HttpKernel; -use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; -use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use App\Http\Middleware\SetDbByCompanyKey; +use App\Http\Middleware\ValidateSignature; +use App\Http\Middleware\PasswordProtection; +use App\Http\Middleware\ClientPortalEnabled; +use App\Http\Middleware\CheckClientExistence; +use App\Http\Middleware\VendorContactKeyLogin; use Illuminate\Http\Middleware\SetCacheHeaders; -use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Session\Middleware\StartSession; +use App\Http\Middleware\CheckForMaintenanceMode; +use App\Http\Middleware\RedirectIfAuthenticated; +use Illuminate\Foundation\Http\Kernel as HttpKernel; +use Illuminate\Auth\Middleware\EnsureEmailIsVerified; +use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; +use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; +use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; class Kernel extends HttpKernel { @@ -150,6 +151,7 @@ class Kernel extends HttpKernel 'portal_enabled' => ClientPortalEnabled::class, 'url_db' => UrlSetDb::class, 'web_db' => SetWebDb::class, + 'api_db' => SetDb::class, 'company_key_db' => SetDbByCompanyKey::class, 'locale' => Locale::class, 'vendor_locale' => VendorLocale::class, @@ -172,6 +174,7 @@ class Kernel extends HttpKernel SessionDomains::class, Cors::class, SetDomainNameDb::class, + SetDb::class, SetWebDb::class, UrlSetDb::class, ContactSetDb::class, diff --git a/app/Http/Middleware/SetDb.php b/app/Http/Middleware/SetDb.php new file mode 100644 index 0000000000..6b8bd50c86 --- /dev/null +++ b/app/Http/Middleware/SetDb.php @@ -0,0 +1,48 @@ + 'Invalid Token', + 'errors' => new stdClass(), + ]; + + if ($request->header('X-API-TOKEN') && config('ninja.db.multi_db_enabled')) { + if (! MultiDB::findAndSetDb($request->header('X-API-TOKEN'))) { + return response()->json($error, 403); + } + } elseif (! config('ninja.db.multi_db_enabled')) { + return $next($request); + } else { + return response()->json($error, 403); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/TokenAuth.php b/app/Http/Middleware/TokenAuth.php index c0e5770c84..e921459ff2 100644 --- a/app/Http/Middleware/TokenAuth.php +++ b/app/Http/Middleware/TokenAuth.php @@ -32,17 +32,18 @@ class TokenAuth */ public function handle($request, Closure $next) { - if (config('ninja.db.multi_db_enabled') && - $request->header('X-API-TOKEN') && - ($company_token = MultiDB::getCompanyToken($request->header('X-API-TOKEN')))) { - } elseif ($request->header('X-API-TOKEN') && ($company_token = CompanyToken::with([ + + if ($request->header('X-API-TOKEN') && ($company_token = CompanyToken::with([ 'user.account', 'company', 'account', + 'cu', ])->where('token', $request->header('X-API-TOKEN'))->first())) { + } else { return response()->json(['message' => 'Invalid token'], 403); } + $user = $company_token->user; $error = [ @@ -83,7 +84,6 @@ class TokenAuth */ app('queue')->createPayloadUsing(function () use ($company_token) { return ['db' => $company_token->company->db]; - // return ['db' => $company_token->company->db, 'is_premium' => $company_token->account->isPremium()]; }); //user who once existed, but has been soft deleted diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index 1bc2bbb483..f6e34cc82b 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -84,7 +84,7 @@ class BaseImport ) : null; - auth()->login($this->company->owner(), true); + auth()->login($this->company->owner(), false); /** @var \App\Models\User $user */ $user = auth()->user(); diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index a90d879be0..d13b045fa0 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -51,13 +51,13 @@ class CreateAccount public function handle() { - if (config('ninja.environment') == 'selfhost' && Account::count() == 0) { - return $this->create(); - } elseif (config('ninja.environment') == 'selfhost' && Account::count() > 1) { - return response()->json(['message' => Ninja::selfHostedMessage()], 400); - } elseif (! Ninja::boot()) { - return response()->json(['message' => Ninja::parse()], 401); - } + // if (config('ninja.environment') == 'selfhost' && Account::count() == 0) { + // return $this->create(); + // } elseif (config('ninja.environment') == 'selfhost' && Account::count() > 1) { + // return response()->json(['message' => Ninja::selfHostedMessage()], 400); + // } elseif (! Ninja::boot()) { + // return response()->json(['message' => Ninja::parse()], 401); + // } return $this->create(); } @@ -115,6 +115,7 @@ class CreateAccount event(new AccountCreated($spaa9f78, $sp035a66, Ninja::eventVars())); } + $spaa9f78->fresh(); if (Ninja::isHosted()) { diff --git a/app/Jobs/Util/WebhookHandler.php b/app/Jobs/Util/WebhookHandler.php index 039e244b83..2b67b5a2a1 100644 --- a/app/Jobs/Util/WebhookHandler.php +++ b/app/Jobs/Util/WebhookHandler.php @@ -29,11 +29,12 @@ class WebhookHandler implements ShouldQueue use Queueable; use SerializesModels; - public $tries = 1; //number of retries + public $timeout = 30; + public $deleteWhenMissingModels = true; - + /** * Create a new job instance. * @@ -66,6 +67,11 @@ class WebhookHandler implements ShouldQueue }); } + public function viaQueue() + { + return \App\Utils\Ninja::isHosted() ? 'webhooks' : 'default'; + } + public function failed($exception = null) { } diff --git a/app/Libraries/MultiDB.php b/app/Libraries/MultiDB.php index ebbbbcec81..02f92f9a18 100644 --- a/app/Libraries/MultiDB.php +++ b/app/Libraries/MultiDB.php @@ -208,7 +208,7 @@ class MultiDB foreach (self::$dbs as $db) { self::setDB($db); - if ($user = User::where($data)->withTrashed()->first()) { + if ($user = User::on($db)->where($data)->withTrashed()->first()) { return $user; } } @@ -653,7 +653,7 @@ class MultiDB foreach (self::$dbs as $db) { self::setDB($db); - if ($exists = Account::where('account_sms_verification_number', $phone)->where('account_sms_verified', true)->exists()) { + if ($exists = Account::on($db)->where('account_sms_verification_number', $phone)->where('account_sms_verified', true)->exists()) { self::setDb($current_db); return true; } diff --git a/app/Models/Account.php b/app/Models/Account.php index bfbabd13ea..eb7d11cc02 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -310,7 +310,7 @@ class Account extends BaseModel } // 09-03-2023 - winds forward expiry checks to ensure we don't cut off users prior to billing cycle being commenced - if ($this->plan_expires && Carbon::parse($this->plan_expires)->lt(now()->subHours(12))) { + if ($this->plan_expires && Carbon::parse($this->plan_expires)->lt(now()->subHours(23))) { return false; } diff --git a/app/Models/Client.php b/app/Models/Client.php index ad52770086..32c1627541 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -12,7 +12,7 @@ namespace App\Models; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use App\DataMapper\ClientSync; use App\Utils\Traits\AppSetup; use App\Utils\Traits\MakesHash; diff --git a/app/Models/ClientContact.php b/app/Models/ClientContact.php index 73762a6c22..8ca2551742 100644 --- a/app/Models/ClientContact.php +++ b/app/Models/ClientContact.php @@ -14,7 +14,7 @@ namespace App\Models; use App\Utils\Ninja; use Illuminate\Support\Str; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use App\Jobs\Mail\NinjaMailer; use App\Utils\Traits\AppSetup; use App\Utils\Traits\MakesHash; diff --git a/app/Models/CompanyToken.php b/app/Models/CompanyToken.php index d87bdc63b5..19672fd4ba 100644 --- a/app/Models/CompanyToken.php +++ b/app/Models/CompanyToken.php @@ -84,9 +84,7 @@ class CompanyToken extends BaseModel public function company_user(): \Illuminate\Database\Eloquent\Relations\HasOne { - return $this->hasOne(CompanyUser::class, 'user_id', 'user_id') - ->where('company_id', $this->company_id) - ->where('user_id', $this->user_id); + return $this->hasOne(CompanyUser::class, ['user_id', 'company_id'], ['user_id', 'company_id']); } /** @@ -94,8 +92,24 @@ class CompanyToken extends BaseModel */ public function cu() { - return $this->hasOne(CompanyUser::class, 'user_id', 'user_id') - ->where('company_id', $this->company_id) - ->where('user_id', $this->user_id); + return $this->hasOne(CompanyUser::class, ['user_id', 'company_id'], ['user_id', 'company_id']); } + + + // public function company_user(): \Illuminate\Database\Eloquent\Relations\HasOne + // { + // return $this->hasOne(CompanyUser::class, 'user_id', 'user_id') + // ->where('company_id', $this->company_id) + // ->where('user_id', $this->user_id); + // } + + // /** + // * @return \Awobaz\Compoships\Database\Eloquent\Relations\HasOne + // */ + // public function cu() + // { + // return $this->hasOne(CompanyUser::class, 'user_id', 'user_id') + // ->where('company_id', $this->company_id) + // ->where('user_id', $this->user_id); + // } } diff --git a/app/Models/Credit.php b/app/Models/Credit.php index f3580db888..67a32de32b 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -14,7 +14,7 @@ namespace App\Models; use App\Utils\Ninja; use App\Utils\Number; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use Illuminate\Support\Carbon; use App\Utils\Traits\MakesHash; use App\Helpers\Invoice\InvoiceSum; diff --git a/app/Models/CreditInvitation.php b/app/Models/CreditInvitation.php index f2f2935502..18b59a8d32 100644 --- a/app/Models/CreditInvitation.php +++ b/app/Models/CreditInvitation.php @@ -153,6 +153,7 @@ class CreditInvitation extends BaseModel public function markViewed() { $this->viewed_date = Carbon::now(); + $this->credit->last_viewed = Carbon::now(); $this->save(); } diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 1002492dbb..6f27da21d9 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -13,7 +13,7 @@ namespace App\Models; use App\Utils\Number; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use Illuminate\Support\Facades\App; use Illuminate\Database\Eloquent\SoftDeletes; diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 283768f99d..ca43a26a4c 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -271,7 +271,7 @@ class Invoice extends BaseModel 'custom_value4' => (string)$this->custom_value4, 'company_key' => $this->company->company_key, 'po_number' => (string)$this->po_number, - 'line_items' => $this->line_items, + // 'line_items' => $this->line_items, ]; } diff --git a/app/Models/InvoiceInvitation.php b/app/Models/InvoiceInvitation.php index f1628148e2..4b60376efe 100644 --- a/app/Models/InvoiceInvitation.php +++ b/app/Models/InvoiceInvitation.php @@ -148,6 +148,7 @@ class InvoiceInvitation extends BaseModel public function markViewed(): void { $this->viewed_date = Carbon::now(); + $this->invoice->last_viewed = Carbon::now(); $this->save(); } diff --git a/app/Models/PurchaseOrder.php b/app/Models/PurchaseOrder.php index bd4a105f3c..a93b1cf4f0 100644 --- a/app/Models/PurchaseOrder.php +++ b/app/Models/PurchaseOrder.php @@ -14,7 +14,7 @@ namespace App\Models; use App\Utils\Ninja; use App\Utils\Number; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use Illuminate\Support\Carbon; use App\Helpers\Invoice\InvoiceSum; use Illuminate\Support\Facades\App; diff --git a/app/Models/PurchaseOrderInvitation.php b/app/Models/PurchaseOrderInvitation.php index 9ae8ecfdd4..bf822f3013 100644 --- a/app/Models/PurchaseOrderInvitation.php +++ b/app/Models/PurchaseOrderInvitation.php @@ -139,6 +139,7 @@ class PurchaseOrderInvitation extends BaseModel public function markViewed(): void { $this->viewed_date = Carbon::now(); + $this->purchase_order->last_viewed = Carbon::now(); $this->save(); } diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 36295a4daf..992456593b 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -15,7 +15,7 @@ namespace App\Models; use App\Utils\Ninja; use App\Utils\Number; use App\DataMapper\QuoteSync; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use Illuminate\Support\Carbon; use App\Utils\Traits\MakesHash; use App\Helpers\Invoice\InvoiceSum; diff --git a/app/Models/QuoteInvitation.php b/app/Models/QuoteInvitation.php index 3a56c04281..870394793e 100644 --- a/app/Models/QuoteInvitation.php +++ b/app/Models/QuoteInvitation.php @@ -139,6 +139,7 @@ class QuoteInvitation extends BaseModel public function markViewed() { $this->viewed_date = Carbon::now(); + $this->quote->last_viewed = Carbon::now(); $this->save(); } diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index d6ee6df2d2..d4dec50630 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -13,7 +13,7 @@ namespace App\Models; use App\Utils\Number; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use Illuminate\Support\Carbon; use App\Utils\Traits\MakesHash; use App\Helpers\Invoice\InvoiceSum; diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 890e10f724..99ef857753 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -12,7 +12,7 @@ namespace App\Models; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use App\Utils\Traits\AppSetup; use App\DataMapper\CompanySettings; use Illuminate\Support\Facades\App; diff --git a/app/Models/VendorContact.php b/app/Models/VendorContact.php index 81b0532637..a7e9d93149 100644 --- a/app/Models/VendorContact.php +++ b/app/Models/VendorContact.php @@ -12,7 +12,7 @@ namespace App\Models; -use Laravel\Scout\Searchable; +use Elastic\ScoutDriverPlus\Searchable; use App\Utils\Traits\MakesHash; use Illuminate\Support\Facades\Cache; use Illuminate\Database\Eloquent\Model; diff --git a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php index 23580a5415..548ced05e1 100644 --- a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php +++ b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php @@ -80,6 +80,7 @@ class AuthorizeCreditCard implements LivewireMethodInterface if ($request->has('store_card') && $request->input('store_card') === true) { $authorise_payment_method = new AuthorizePaymentMethod($this->authorize); + $authorise_payment_method->setPaymentMethodId(\App\Models\GatewayType::CREDIT_CARD); $payment_profile = $authorise_payment_method->addPaymentMethodToClient($gateway_customer_reference, $data); $payment_profile_id = $payment_profile->getPaymentProfile()->getCustomerPaymentProfileId(); @@ -233,7 +234,7 @@ class AuthorizeCreditCard implements LivewireMethodInterface private function processSuccessfulResponse($data, $request) { $payment_hash = PaymentHash::where('hash', $request->input('payment_hash'))->firstOrFail(); - $payment = $this->storePayment($payment_hash, $data); + $payment = $this->storePayment($payment_hash, $data, \App\Models\GatewayType::CREDIT_CARD); $vars = [ 'invoices' => $payment_hash->invoices(), diff --git a/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php b/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php index f585abb587..4695295ab2 100644 --- a/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php +++ b/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php @@ -39,6 +39,12 @@ class AuthorizePaymentMethod private $payment_method_id; + public function setPaymentMethodId($payment_method_id) + { + $this->payment_method_id = $payment_method_id; + return $this; + } + public function __construct(AuthorizePaymentDriver $authorize) { $this->authorize = $authorize; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index ace5c61d90..59f0a49fc0 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -83,10 +83,9 @@ class AppServiceProvider extends ServiceProvider /* Ensure we don't have stale state in jobs */ Queue::before(function (JobProcessing $event) { - App::forgetInstance('truthsource'); + App::forgetInstance(TruthSource::class); }); - /* Always init a new instance everytime the container boots */ app()->instance(TruthSource::class, new TruthSource()); /* Extension for custom mailers */ @@ -155,5 +154,6 @@ class AppServiceProvider extends ServiceProvider public function register(): void { + } } diff --git a/app/Repositories/ActivityRepository.php b/app/Repositories/ActivityRepository.php index d956b39595..f35904a725 100644 --- a/app/Repositories/ActivityRepository.php +++ b/app/Repositories/ActivityRepository.php @@ -119,7 +119,7 @@ class ActivityRepository extends BaseRepository public function getTokenId(array $event_vars) { - if ($event_vars['token']) { + if (isset($event_vars['token']) &&$event_vars['token']) { /** @var \App\Models\CompanyToken $company_token **/ $company_token = CompanyToken::query()->where('token', $event_vars['token'])->first(); diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 3b10326534..288c62577b 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -92,7 +92,7 @@ class UserRepository extends BaseRepository /*No company user exists - attach the user*/ if (! $cu) { $data['company_user']['account_id'] = $account->id; - $data['company_user']['notifications'] = CompanySettings::notificationDefaults(); + $data['company_user']['notifications'] = isset($data['company_user']['notifications']['email']) ? $data['company_user']['notifications'] : CompanySettings::notificationDefaults(); $user->companies()->attach($company->id, $data['company_user']); } else { if (auth()->user()->isAdmin()) { diff --git a/composer.json b/composer.json index 17a06e6b32..0a99725f18 100644 --- a/composer.json +++ b/composer.json @@ -226,8 +226,8 @@ "url": "https://github.com/turbo124/snappdf" }, { - "type": "path", - "url": "../admin-api" + "type": "vcs", + "url": "https://github.com/invoiceninja/admin-api" } ], "minimum-stability": "dev", diff --git a/composer.lock b/composer.lock index a2839e0932..160b4e9b62 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4361272676d998d08fb1926198065b39", + "content-hash": "4c133d6a99108c7c4e779dfdab4457e3", "packages": [ { "name": "adrienrn/php-mimetyper", diff --git a/config/ninja.php b/config/ninja.php index 77e4a9fe4e..98a25d2745 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION', '5.11.79'), - 'app_tag' => env('APP_TAG', '5.11.79'), + 'app_version' => env('APP_VERSION', '5.11.80'), + 'app_tag' => env('APP_TAG', '5.11.80'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/phpstan.neon b/phpstan.neon index 88abf4d150..ad438b6769 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -20,6 +20,7 @@ parameters: - 'app/PaymentDrivers/AuthorizePaymentDriver.php' - 'app/Http/Middleware/ThrottleRequestsWithPredis.php' - 'app/Utils/Traits/*' + - 'Modules/Accounting/*' universalObjectCratesClasses: - App\DataMapper\Tax\RuleInterface - App\DataMapper\FeesAndLimits diff --git a/routes/api.php b/routes/api.php index e34a5f0730..0e71b6111e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -139,7 +139,7 @@ Route::group(['middleware' => ['throttle:login', 'api_secret_check', 'email_db'] Route::post('api/v1/reset_password', [ForgotPasswordController::class, 'sendResetLinkEmail']); }); -Route::group(['middleware' => ['throttle:api', 'token_auth', 'valid_json','locale'], 'prefix' => 'api/v1', 'as' => 'api.'], function () { +Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'valid_json','locale'], 'prefix' => 'api/v1', 'as' => 'api.'], function () { Route::post('password_timeout', PasswordTimeoutController::class)->name('password_timeout'); Route::put('accounts/{account}', [AccountController::class, 'update'])->name('account.update'); diff --git a/tests/Feature/Import/CSV/CsvImportTest.php b/tests/Feature/Import/CSV/CsvImportTest.php index 7ec6269d07..a6f21f6988 100644 --- a/tests/Feature/Import/CSV/CsvImportTest.php +++ b/tests/Feature/Import/CSV/CsvImportTest.php @@ -45,7 +45,7 @@ class CsvImportTest extends TestCase $this->withoutExceptionHandling(); - auth()->login($this->user); + // auth()->login($this->user); } public function testRecurringInvoiceImport() @@ -119,6 +119,8 @@ class CsvImportTest extends TestCase Cache::put($hash.'-recurring_invoice', base64_encode($csv), 360); + // $this->user->setContext($this->company, $this->token); + $truth = app()->make(TruthSource::class); $truth->setCompanyUser($this->cu); $truth->setUser($this->user); @@ -355,10 +357,12 @@ class CsvImportTest extends TestCase Cache::put($hash.'-invoice', base64_encode($csv), 360); - $truth = app()->make(TruthSource::class); - $truth->setCompanyUser($this->cu); - $truth->setUser($this->user); - $truth->setCompany($this->company); + // $this->user->setContext($this->company, $this->token); + + // $truth = app()->make(TruthSource::class); + // $truth->setCompanyUser($this->cu); + // $truth->setUser($this->user); + // $truth->setCompany($this->company); $csv_importer = new Csv($data, $this->company); diff --git a/tests/Feature/UserTest.php b/tests/Feature/UserTest.php index 1186baca23..a86511c18a 100644 --- a/tests/Feature/UserTest.php +++ b/tests/Feature/UserTest.php @@ -11,22 +11,24 @@ namespace Tests\Feature; -use App\DataMapper\CompanySettings; -use App\Factory\CompanyUserFactory; -use App\Http\Middleware\PasswordProtection; +use Tests\TestCase; +use App\Models\User; use App\Models\Account; use App\Models\Company; -use App\Models\CompanyToken; +use App\Libraries\MultiDB; +use App\Utils\TruthSource; +use Tests\MockAccountData; use App\Models\CompanyUser; -use App\Models\User; +use App\Models\CompanyToken; +use App\DataMapper\CompanySettings; +use App\Factory\CompanyUserFactory; use App\Repositories\UserRepository; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Support\Facades\Session; +use App\Http\Middleware\PasswordProtection; use Illuminate\Validation\ValidationException; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @@ -35,7 +37,6 @@ use Tests\TestCase; class UserTest extends TestCase { use MockAccountData; - use DatabaseTransactions; private $default_email = 'attach@gmail.com'; @@ -52,7 +53,7 @@ class UserTest extends TestCase PasswordProtection::class ); - $this->makeTestData(); + // $this->makeTestData(); // $this->withoutExceptionHandling(); @@ -73,9 +74,14 @@ class UserTest extends TestCase 'account_id' => $account->id, 'confirmation_code' => 'xyz123', 'email' => $this->faker->unique()->safeEmail(), - 'password' => \Illuminate\Support\Facades\Hash::make('ALongAndBriliantPassword'), ]); + $user->password = \Illuminate\Support\Facades\Hash::make('ALongAndBriliantPassword'); + $user->email_verified_at = now(); + $user->save(); + + auth()->login($user, false); + $settings = CompanySettings::defaults(); $settings->client_online_payment_notification = false; $settings->client_manual_payment_notification = false; @@ -85,11 +91,21 @@ class UserTest extends TestCase 'settings' => $settings, ]); - $cu = CompanyUserFactory::create($user->id, $company->id, $account->id); - $cu->is_owner = true; - $cu->is_admin = true; - $cu->is_locked = false; - $cu->save(); + // $cu = CompanyUserFactory::create($user->id, $company->id, $account->id); + // $cu->is_owner = true; + // $cu->is_admin = true; + // $cu->is_locked = false; + // $cu->save(); + + $user->companies()->attach($company->id, [ + 'account_id' => $account->id, + 'is_owner' => 1, + 'is_admin' => 1, + 'is_locked' => 0, + 'permissions' => '', + 'notifications' => \App\DataMapper\CompanySettings::notificationAdminDefaults(), + 'settings' => null, + ]); $token = \Illuminate\Support\Str::random(64); @@ -102,55 +118,31 @@ class UserTest extends TestCase $company_token->is_system = true; $company_token->save(); + // auth()->user()->setContext($company, $company_token); + + $truth = app()->make(TruthSource::class); + + $truth->setCompanyUser($company_token->cu); + $truth->setUser($company_token->user); + $truth->setCompany($company_token->company); + $truth->setCompanyToken($company_token); + return $company_token; } - // public function testCrossAccountFunctionality() - // { - // $ct = $this->mockAccount(); - - // $u= $ct->user; - - // auth()->login($u, true); - - // $account = Account::factory()->create([ - // 'hosted_client_count' => 1000, - // 'hosted_company_count' => 1000, - // ]); - - // $account->num_users = 3; - // $account->save(); - - // $user = User::factory()->create([ - // 'account_id' => $this->account->id, - // 'confirmation_code' => 'xyz123', - // 'email' => $this->faker->unique()->safeEmail(), - // 'password' => \Illuminate\Support\Facades\Hash::make('ALongAndBriliantPassword'), - // ]); - - - // $user_repo = new UserRepository(); - - - // // try{ - // $x = $user_repo->save(['first_name' => 'bobby'], $user); - // // } - // // catch(\Exception $e){ - - // // $this->assertEquals(401, $e->getCode()); - // // } - - // nlog($x); - - - // } public function testValidEmailUpdate() { $company_token = $this->mockAccount(); - $user = $company_token->user; - $user->load('company_user'); + $user = auth()->user(); + + // $user = $company_token->user; + // $user->load('company_user'); + // nlog($company_token->toArray()); + + // $user = User::with('company_user')->find($company_token->user_id); + // nlog($user->toArray()); $data = $user->toArray(); @@ -162,6 +154,19 @@ class UserTest extends TestCase $response->assertStatus(200); + $data['email'] = 'newemail@gmail.com'; + + // $response = $this->withHeaders([ + // 'X-API-SECRET' => config('ninja.api_secret'), + // 'X-API-TOKEN' => $company_token->token, + // 'X-API-PASSWORD' => 'ALongAndBriliantPassword', + // ])->putJson('/api/v1/users/'.$user->hashed_id.'?include=company_user', $data); + + + // $response->assertStatus(200); + + // $data = $response->json(); + // $this->assertEquals($data['data']['email'], $data['email']); } @@ -169,9 +174,11 @@ class UserTest extends TestCase { $company_token = $this->mockAccount(); - $user = $company_token->user; - $user->load('company_user'); + // $user = $company_token->user; + // $user->load('company_user'); + $user = auth()->user(); + $data = $user->toArray(); $data['email'] = ''; unset($data['password']); @@ -215,14 +222,19 @@ class UserTest extends TestCase public function testUserLocale() { - $this->user->language_id = "13"; - $this->user->save(); + + $company_token = $this->mockAccount(); - $this->assertEquals("fr_CA", $this->user->getLocale()); + $user = auth()->user(); + + $user->language_id = "13"; + $user->save(); + + $this->assertEquals("fr_CA", $user->getLocale()); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, ])->get('/api/v1/statics'); $response->assertStatus(200); @@ -235,6 +247,12 @@ class UserTest extends TestCase { $company_token = $this->mockAccount(); + $_user = MultiDB::hasUser(['email' => 'normal_user@gmail.com']); + + if($_user) { + $_user->account->delete(); + } + $data = [ 'first_name' => 'hey', 'last_name' => 'you', @@ -337,7 +355,7 @@ class UserTest extends TestCase $account->save(); $user = User::factory()->create([ - 'account_id' => $this->account->id, + 'account_id' => $account->id, 'confirmation_code' => 'xyz123', 'email' => $this->faker->unique()->safeEmail(), 'password' => \Illuminate\Support\Facades\Hash::make('ALongAndBriliantPassword'), @@ -352,12 +370,15 @@ class UserTest extends TestCase 'settings' => $settings, ]); - - $cu = CompanyUserFactory::create($user->id, $company->id, $account->id); - $cu->is_owner = true; - $cu->is_admin = true; - $cu->is_locked = false; - $cu->save(); + $user->companies()->attach($company->id, [ + 'account_id' => $account->id, + 'is_owner' => 1, + 'is_admin' => 1, + 'is_locked' => 0, + 'permissions' => '', + 'notifications' => \App\DataMapper\CompanySettings::notificationAdminDefaults(), + 'settings' => null, + ]); $token = \Illuminate\Support\Str::random(64); @@ -385,45 +406,56 @@ class UserTest extends TestCase } - public function testDisconnectUserOauthMailer() - { - $user = - User::factory()->create([ - 'account_id' => $this->account->id, - 'email' => $this->faker->safeEmail(), - 'oauth_user_id' => '123456789', - 'oauth_provider_id' => '123456789', - ]); + // public function testDisconnectUserOauthMailer() + // { + // $account = Account::factory()->create([ + // 'hosted_client_count' => 1000, + // 'hosted_company_count' => 1000, + // ]); - $response = $this->withHeaders([ - 'X-API-TOKEN' => $this->token, - ])->post("/api/v1/users/{$user->hashed_id}/disconnect_mailer"); + // $user = + // User::factory()->create([ + // 'account_id' => $account->id, + // 'email' => $this->faker->safeEmail(), + // 'oauth_user_id' => '123456789', + // 'oauth_provider_id' => '123456789', + // ]); - $response->assertStatus(200); + // $response = $this->withHeaders([ + // 'X-API-TOKEN' => $this->token, + // ])->post("/api/v1/users/{$user->hashed_id}/disconnect_mailer"); - $user->fresh(); + // $response->assertStatus(200); - $this->assertNull($user->oauth_user_token); - $this->assertNull($user->oauth_user_refresh_token); + // $user->fresh(); - } + // $this->assertNull($user->oauth_user_token); + // $this->assertNull($user->oauth_user_refresh_token); + + // } public function testUserFiltersWith() { + $company_token = $this->mockAccount(); + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', - ])->get('/api/v1/users?with='.$this->user->hashed_id); + ])->get('/api/v1/users?with='.$company_token->user->hashed_id); $response->assertStatus(200); } public function testUserList() { + + + $company_token = $this->mockAccount(); + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->get('/api/v1/users'); @@ -433,6 +465,13 @@ class UserTest extends TestCase public function testValidationRulesPhoneIsNull() { $this->withoutMiddleware(PasswordProtection::class); + $company_token = $this->mockAccount(); + + $_user = MultiDB::hasUser(['email' => 'bob1@good.ole.boys.com']); + + if ($_user) { + $_user->account->delete(); + } $data = [ 'first_name' => 'hey', @@ -448,7 +487,7 @@ class UserTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->postJson('/api/v1/users?include=company_user', $data); @@ -459,6 +498,13 @@ class UserTest extends TestCase { $this->withoutMiddleware(PasswordProtection::class); + $_user = MultiDB::hasUser(['email' => 'bob1@good.ole.boys.com']); + + if($_user) { + $_user->account->delete(); + } + + $company_token = $this->mockAccount(); $data = [ 'first_name' => 'hey', 'last_name' => 'you', @@ -473,7 +519,7 @@ class UserTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->postJson('/api/v1/users?include=company_user', $data); @@ -500,7 +546,7 @@ class UserTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->putJson('/api/v1/users/'.$user->hashed_id.'?include=company_user', $data); } @@ -509,6 +555,14 @@ class UserTest extends TestCase { $this->withoutMiddleware(PasswordProtection::class); + + $_user = MultiDB::hasUser(['email' => 'bob1@good.ole.boys.com']); + + if($_user) { + $_user->account->delete(); + } + + $company_token = $this->mockAccount(); $data = [ 'first_name' => 'hey', 'last_name' => 'you', @@ -523,7 +577,7 @@ class UserTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->postJson('/api/v1/users?include=company_user', $data); @@ -538,6 +592,13 @@ class UserTest extends TestCase { $this->withoutMiddleware(PasswordProtection::class); + $_user = MultiDB::hasUser(['email' => $this->default_email]); + + if ($_user) { + $_user->account->delete(); + } + + $company_token = $this->mockAccount(); $data = [ 'first_name' => 'Test', 'last_name' => 'Palloni', @@ -548,7 +609,7 @@ class UserTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->postJson('/api/v1/users?include=company_user', $data); @@ -558,7 +619,7 @@ class UserTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, + 'X-API-TOKEN' => $company_token->token, 'X-API-PASSWORD' => 'ALongAndBriliantPassword', ])->delete('/api/v1/users/'.$arr['data']['id'].'/detach_from_company?include=company_user'); @@ -566,8 +627,8 @@ class UserTest extends TestCase $user_id = $this->decodePrimaryKey($arr['data']['id']); - $cu = CompanyUser::whereUserId($user_id)->whereCompanyId($this->company->id)->first(); - $ct = CompanyToken::whereUserId($user_id)->whereCompanyId($this->company->id)->first(); + $cu = CompanyUser::whereUserId($user_id)->whereCompanyId($company_token->company->id)->first(); + $ct = CompanyToken::whereUserId($user_id)->whereCompanyId($company_token->company->id)->first(); $user = User::find($user_id); $this->assertNull($cu); @@ -579,25 +640,46 @@ class UserTest extends TestCase { $this->withoutMiddleware(PasswordProtection::class); + $company_token = $this->mockAccount(); + + $_user = MultiDB::hasUser(['email' => $this->default_email]); + + if ($_user) { + $_user->account->delete(); + } + + + $_user = MultiDB::hasUser(['email' => 'bob@good.ole.boys.co2.com']); + + if ($_user) { + $_user->account->delete(); + } + + /* Create New Company */ $company2 = Company::factory()->create([ - 'account_id' => $this->account->id, + 'account_id' => $company_token->account_id, ]); $company_token = new CompanyToken(); - $company_token->user_id = $this->user->id; + $company_token->user_id = auth()->user()->id; $company_token->company_id = $company2->id; - $company_token->account_id = $this->account->id; + $company_token->account_id = auth()->user()->account_id; $company_token->name = 'test token'; $company_token->token = \Illuminate\Support\Str::random(64); $company_token->is_system = true; $company_token->save(); /*Manually link this user to the company*/ - $cu = CompanyUserFactory::create($this->user->id, $company2->id, $this->account->id); - $cu->is_owner = true; - $cu->is_admin = true; - $cu->save(); + auth()->user()->companies()->attach($company2->id, [ + 'account_id' => $company_token->account_id, + 'is_owner' => 1, + 'is_admin' => 1, + 'is_locked' => 0, + 'permissions' => '', + 'notifications' => \App\DataMapper\CompanySettings::notificationAdminDefaults(), + 'settings' => null, + ]); /*Create New Blank User and Attach to Company 2*/ $data = [ diff --git a/tests/Integration/MultiDBUserTest.php b/tests/Integration/MultiDBUserTest.php index 14c07204e6..76bdecf3d0 100644 --- a/tests/Integration/MultiDBUserTest.php +++ b/tests/Integration/MultiDBUserTest.php @@ -35,12 +35,25 @@ class MultiDBUserTest extends TestCase { parent::setUp(); - $this->withoutExceptionHandling(); + // $this->withoutExceptionHandling(); if (! config('ninja.db.multi_db_enabled')) { $this->markTestSkipped('Multi DB not enabled - skipping'); } + foreach(MultiDB::getDBs() as $db) { + MultiDB::setDB($db); + $u = User::where('email','db1@example.com')->first(); + if($u) + $u->account->delete(); + + + $u = User::where('email', 'db2@example.com')->first(); + if ($u) { + $u->account->delete(); + } + } + User::unguard(); $ac = Account::factory()->make(); @@ -202,7 +215,7 @@ class MultiDBUserTest extends TestCase ])->postJson('/api/v1/users?include=company_user', $data); - $response->assertStatus(403); + $response->assertStatus(422); } @@ -241,9 +254,30 @@ class MultiDBUserTest extends TestCase { parent::tearDown(); - DB::connection('db-ninja-01')->table('users')->delete(); - DB::connection('db-ninja-02')->table('users')->delete(); + + $u = User::on('db-ninja-01')->where('email', 'db1@example.com')->first(); + if ($u) { + $u->account->delete(); + } - config(['database.default' => config('ninja.db.default')]); + + $u = User::on('db-ninja-01')->where('email', 'db2@example.com')->first(); + if ($u) { + $u->account->delete(); + } + + + $u = User::on('db-ninja-02')->where('email', 'db1@example.com')->first(); + if ($u) { + $u->account->delete(); + } + + + $u = User::on('db-ninja-02')->where('email', 'db2@example.com')->first(); + if ($u) { + $u->account->delete(); + } + + } } diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 867505d598..9099959d39 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -272,8 +272,8 @@ trait MockAccountData $user_id = $user->id; $this->user = $user; - // auth()->login($user); - // auth()->user()->setCompany($this->company); + auth()->login($user, false); + auth()->user()->setCompany($this->company); CreateCompanyTaskStatuses::dispatchSync($this->company, $this->user); @@ -295,6 +295,8 @@ trait MockAccountData $company_token->save(); + // $user->setContext($this->company, $company_token); + $truth = app()->make(TruthSource::class); $truth->setCompanyUser($company_token->first()); $truth->setUser($this->user);