From b475659248e5e06e01a8182080c06bcd09d48a8f Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Tue, 8 Mar 2022 21:58:42 -0500 Subject: [PATCH 01/41] feat: subscribe with the customer portal instead of stripe --- .../NoCustomerPortalSetException.php | 9 + .../NoLicenceKeyEncryptionSetException.php | 9 + app/Helpers/InstanceHelper.php | 10 - .../Settings/SubscriptionsController.php | 81 +- app/Models/Account/Account.php | 12 + .../Subscription/ActivateLicenceKey.php | 105 ++ .../Subscription/ValidateLicenceKey.php | 46 + app/Traits/Subscription.php | 10 +- composer.lock | 1371 +++++++++-------- config/monica.php | 22 + ...08_115818_add_licence_keys_to_accounts.php | 36 + package.json | 2 +- resources/lang/en/settings.php | 11 +- .../settings/subscriptions/account.blade.php | 43 +- .../settings/subscriptions/blank.blade.php | 35 +- .../settings/subscriptions/success.blade.php | 2 +- routes/web.php | 2 + tests/Feature/AccountSubscriptionTest.php | 16 - tests/Unit/Helpers/InstanceHelperTest.php | 13 - tests/Unit/Models/AccountTest.php | 43 +- .../Subscription/ActivateLicenceKeyTest.php | 92 ++ 21 files changed, 1159 insertions(+), 811 deletions(-) create mode 100644 app/Exceptions/NoCustomerPortalSetException.php create mode 100644 app/Exceptions/NoLicenceKeyEncryptionSetException.php create mode 100644 app/Services/Account/Subscription/ActivateLicenceKey.php create mode 100644 app/Services/Account/Subscription/ValidateLicenceKey.php create mode 100644 database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php create mode 100644 tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php diff --git a/app/Exceptions/NoCustomerPortalSetException.php b/app/Exceptions/NoCustomerPortalSetException.php new file mode 100644 index 00000000000..7d3a1add1e6 --- /dev/null +++ b/app/Exceptions/NoCustomerPortalSetException.php @@ -0,0 +1,9 @@ +count(); - } - /** * Get the plan information for the given time period. * diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index 85536184fdf..b0de037ebd1 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Settings; +use App\Exceptions\NoLicenceKeyEncryptionSetException; use Illuminate\View\View; use App\Traits\StripeCall; use App\Helpers\DateHelper; @@ -11,6 +12,7 @@ use App\Helpers\AccountHelper; use App\Helpers\InstanceHelper; use App\Exceptions\StripeException; +use Illuminate\Validation\ValidationException; use Illuminate\Support\Facades\App; use App\Http\Controllers\Controller; use Illuminate\Http\RedirectResponse; @@ -19,6 +21,8 @@ use Stripe\PaymentIntent as StripePaymentIntent; use Laravel\Cashier\Exceptions\IncompletePayment; use App\Services\Account\Settings\ArchiveAllContacts; +use App\Services\Account\Subscription\ActivateLicenceKey; +use Exception; class SubscriptionsController extends Controller { @@ -37,34 +41,38 @@ public function index() $account = auth()->user()->account; - $subscription = $account->getSubscribedPlan(); - if (! $account->isSubscribed() && (! $subscription || $subscription->ended())) { + if (! $account->isSubscribed()) { return view('settings.subscriptions.blank', [ - 'numberOfCustomers' => InstanceHelper::getNumberOfPaidSubscribers(), + 'customerPortalUrl' => config('monica.customer_portal_url'), ]); } - $hasInvoices = $account->hasStripeId() && $account->hasInvoices(); - $invoices = null; - if ($hasInvoices) { - $invoices = $account->invoices(); - } + return view('settings.subscriptions.account', [ + 'planInformation' => trans('settings.subscriptions_licence_key_frequency_'.$account->frequency), + 'nextBillingDate' => DateHelper::getFullDate($account->valid_until_at), + 'accountHasLimitations' => AccountHelper::hasLimitations($account), + 'customerPortalUrl' => config('monica.customer_portal_url'), + ]); + } + public function store(Request $request) + { try { - $planInformation = $this->stripeCall(function () use ($subscription) { - return InstanceHelper::getPlanInformationFromSubscription($subscription); - }); - } catch (StripeException $e) { - $planInformation = null; + app(ActivateLicenceKey::class)->execute([ + 'account_id' => auth()->user()->account_id, + 'licence_key' => $request->input('licence_key'), + ]); + } catch (ValidationException $e) { + return back() + ->withInput() + ->withErrors($e->validator); + } catch (Exception $e) { + return back() + ->withInput() + ->withErrors($e->getMessage()); } - return view('settings.subscriptions.account', [ - 'planInformation' => $planInformation, - 'subscription' => $subscription, - 'hasInvoices' => $hasInvoices, - 'invoices' => $invoices, - 'accountHasLimitations' => AccountHelper::hasLimitations($account), - ]); + return view('settings.subscriptions.success'); } /** @@ -117,9 +125,7 @@ public function update(Request $request) $subscription = $account->getSubscribedPlan(); if (! $account->isSubscribed() && (! $subscription || $subscription->ended())) { - return view('settings.subscriptions.blank', [ - 'numberOfCustomers' => InstanceHelper::getNumberOfPaidSubscribers(), - ]); + return view('settings.subscriptions.blank'); } $planInformation = InstanceHelper::getPlanInformationFromSubscription($subscription); @@ -276,35 +282,6 @@ public function downgrade() ->with('canDowngrade', AccountHelper::canDowngrade($account)); } - /** - * Process the downgrade process. - * - * @return RedirectResponse - */ - public function processDowngrade() - { - $account = auth()->user()->account; - - if (! AccountHelper::canDowngrade($account)) { - return redirect()->route('settings.subscriptions.downgrade'); - } - - $subscription = $account->getSubscribedPlan(); - if (! $account->isSubscribed() && ! $subscription) { - return redirect()->route('settings.index'); - } - - try { - $account->subscriptionCancel(); - } catch (StripeException $e) { - return back() - ->withInput() - ->withErrors($e->getMessage()); - } - - return redirect()->route('settings.subscriptions.downgrade.success'); - } - /** * Process the upgrade payment. * diff --git a/app/Models/Account/Account.php b/app/Models/Account/Account.php index 4bbb8da2316..7e1e1c41b3a 100644 --- a/app/Models/Account/Account.php +++ b/app/Models/Account/Account.php @@ -66,6 +66,9 @@ class Account extends Model 'api_key', 'default_time_reminder_is_sent', 'default_gender_id', + 'licence_key', + 'valid_until_at', + 'purchaser_email', ]; /** @@ -77,6 +80,15 @@ class Account extends Model 'has_access_to_paid_version_for_free' => 'boolean', ]; + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = [ + 'valid_until_at', + ]; + /** * Get the activity records associated with the account. * diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php new file mode 100644 index 00000000000..2032b6c599e --- /dev/null +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -0,0 +1,105 @@ + 'required|integer|exists:accounts,id', + 'licence_key' => 'required|string:255', + ]; + } + + /** + * Check if the licence key given by the user is a valid licence key. + * If it is, activate the licence key and set the valid_until_at date. + * + * @param array $data + * @return void + */ + public function execute(array $data): void + { + $this->validate($data); + $this->data = $data; + $this->account = Account::findOrFail($data['account_id']); + + $this->validateEnvVariables(); + $this->makeRequestToCustomerPortal(); + $this->checkResponseCode(); + $this->decodeAndStoreKey(); + } + + private function validateEnvVariables(): void + { + if (!config('monica.licence_key_encryption_key')) { + throw new NoLicenceKeyEncryptionSetException(); + } + + if (config('monica.customer_portal_url') == '') { + throw new NoCustomerPortalSetException(); + } + } + + private function makeRequestToCustomerPortal(): void + { + $url = config('monica.customer_portal_url') . '/validate/key/' . $this->data['licence_key']; + + // necessary for testing purposes + if (App::environment('production')) { + $this->response = Http::get($url); + } else { + $this->response = Http::withOptions(['verify' => false])->get($url); + } + } + + private function checkResponseCode(): void + { + if ($this->response->status() == 404) { + throw new Exception(trans('settings.subscriptions_licence_key_does_not_exist')); + } + + if ($this->response->status() == 900) { + throw new Exception(trans('settings.subscriptions_licence_key_invalid')); + } + + if ($this->response->status() != 200) { + throw new Exception(trans('settings.subscriptions_licence_key_problem')); + } + } + + private function decodeAndStoreKey(): void + { + $licenceKey = base64_decode($this->data['licence_key']); + $licenceKey = Str::replace('123', '', $licenceKey); + $array = json_decode($licenceKey, true); + + $this->account->licence_key = $this->data['licence_key']; + $this->account->valid_until_at = $array[0]['next_check_at']; + $this->account->purchaser_email = $array[0]['purchaser_email']; + $this->account->frequency = $array[0]['frequency']; + $this->account->save(); + } +} diff --git a/app/Services/Account/Subscription/ValidateLicenceKey.php b/app/Services/Account/Subscription/ValidateLicenceKey.php new file mode 100644 index 00000000000..a6eee2584b0 --- /dev/null +++ b/app/Services/Account/Subscription/ValidateLicenceKey.php @@ -0,0 +1,46 @@ + 'required|integer|exists:accounts,id', + 'licence_key' => 'required|integer|exists:photos,id', + ]; + } + + /** + * Destroy a photo. + * + * @param array $data + * @return bool + */ + public function execute(array $data): bool + { + $this->validate($data); + + $photo = Photo::where('account_id', $data['account_id']) + ->findOrFail($data['photo_id']); + + // Delete the physical photo + // Throws FileNotFoundException + Storage::delete($photo->new_filename); + + // Delete the object in the DB + $photo->delete(); + + return true; + } +} diff --git a/app/Traits/Subscription.php b/app/Traits/Subscription.php index fd6e00d423a..e891de34952 100644 --- a/app/Traits/Subscription.php +++ b/app/Traits/Subscription.php @@ -77,7 +77,15 @@ public function isSubscribed() return true; } - return $this->getSubscribedPlan() !== null; + if (! $this->licence_key) { + return false; + } + + if ($this->valid_until_at->isPast()) { + return false; + } + + return true; } /** diff --git a/composer.lock b/composer.lock index 13f6b7e9f87..27832cf646d 100644 --- a/composer.lock +++ b/composer.lock @@ -219,16 +219,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.208.7", + "version": "3.212.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "41a800dd7cf5c4ac0ef9bf8db01e838ab6a3698c" + "reference": "1d3db6d276299136bcaa7896653be0dcd2aaa92a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/41a800dd7cf5c4ac0ef9bf8db01e838ab6a3698c", - "reference": "41a800dd7cf5c4ac0ef9bf8db01e838ab6a3698c", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1d3db6d276299136bcaa7896653be0dcd2aaa92a", + "reference": "1d3db6d276299136bcaa7896653be0dcd2aaa92a", "shasum": "" }, "require": { @@ -272,12 +272,12 @@ } }, "autoload": { - "psr-4": { - "Aws\\": "src/" - }, "files": [ "src/functions.php" - ] + ], + "psr-4": { + "Aws\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -304,9 +304,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.208.7" + "source": "https://github.com/aws/aws-sdk-php/tree/3.212.3" }, - "time": "2021-12-21T19:16:39+00:00" + "time": "2022-03-07T19:48:01+00:00" }, { "name": "bacon/bacon-qr-code", @@ -394,12 +394,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Assert\\": "lib/Assert" - }, "files": [ "lib/Assert/functions.php" - ] + ], + "psr-4": { + "Assert\\": "lib/Assert" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -491,16 +491,16 @@ }, { "name": "clue/stream-filter", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/clue/stream-filter.git", - "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320" + "reference": "d6169430c7731d8509da7aecd0af756a5747b78e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/clue/stream-filter/zipball/aeb7d8ea49c7963d3b581378955dbf5bc49aa320", - "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/d6169430c7731d8509da7aecd0af756a5747b78e", + "reference": "d6169430c7731d8509da7aecd0af756a5747b78e", "shasum": "" }, "require": { @@ -541,7 +541,7 @@ ], "support": { "issues": "https://github.com/clue/stream-filter/issues", - "source": "https://github.com/clue/stream-filter/tree/v1.5.0" + "source": "https://github.com/clue/stream-filter/tree/v1.6.0" }, "funding": [ { @@ -553,20 +553,20 @@ "type": "github" } ], - "time": "2020-10-02T12:38:20+00:00" + "time": "2022-02-21T13:15:14+00:00" }, { "name": "colinodell/json5", - "version": "v2.2.1", + "version": "v2.2.2", "source": { "type": "git", "url": "https://github.com/colinodell/json5.git", - "reference": "361fd1bc9175432b789401b616cd3a7b0f862cde" + "reference": "2b0fabd1ba71fe8079a832d6097ec5c6fd92361d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinodell/json5/zipball/361fd1bc9175432b789401b616cd3a7b0f862cde", - "reference": "361fd1bc9175432b789401b616cd3a7b0f862cde", + "url": "https://api.github.com/repos/colinodell/json5/zipball/2b0fabd1ba71fe8079a832d6097ec5c6fd92361d", + "reference": "2b0fabd1ba71fe8079a832d6097ec5c6fd92361d", "shasum": "" }, "require": { @@ -591,16 +591,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { - "psr-4": { - "ColinODell\\Json5\\": "src" - }, "files": [ "src/global.php" - ] + ], + "psr-4": { + "ColinODell\\Json5\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -624,7 +624,7 @@ ], "support": { "issues": "https://github.com/colinodell/json5/issues", - "source": "https://github.com/colinodell/json5/tree/v2.2.1" + "source": "https://github.com/colinodell/json5/tree/v2.2.2" }, "funding": [ { @@ -644,7 +644,7 @@ "type": "patreon" } ], - "time": "2021-11-06T05:25:47+00:00" + "time": "2022-02-22T14:42:16+00:00" }, { "name": "composer/ca-bundle", @@ -722,79 +722,6 @@ ], "time": "2021-10-28T20:44:15+00:00" }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, { "name": "creativeorange/gravatar", "version": "v1.0.21", @@ -1147,20 +1074,20 @@ }, { "name": "doctrine/dbal", - "version": "3.2.0", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "5d54f63541d7bed1156cb5c9b79274ced61890e4" + "reference": "35eae239ef515d55ebb24e9d4715cad09a4f58ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/5d54f63541d7bed1156cb5c9b79274ced61890e4", - "reference": "5d54f63541d7bed1156cb5c9b79274ced61890e4", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/35eae239ef515d55ebb24e9d4715cad09a4f58ed", + "reference": "35eae239ef515d55ebb24e9d4715cad09a4f58ed", "shasum": "" }, "require": { - "composer/package-versions-deprecated": "^1.11.99", + "composer-runtime-api": "^2", "doctrine/cache": "^1.11|^2.0", "doctrine/deprecations": "^0.5.3", "doctrine/event-manager": "^1.0", @@ -1171,14 +1098,14 @@ "require-dev": { "doctrine/coding-standard": "9.0.0", "jetbrains/phpstorm-stubs": "2021.1", - "phpstan/phpstan": "1.2.0", + "phpstan/phpstan": "1.4.0", "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "9.5.10", + "phpunit/phpunit": "9.5.11", "psalm/plugin-phpunit": "0.16.1", - "squizlabs/php_codesniffer": "3.6.1", + "squizlabs/php_codesniffer": "3.6.2", "symfony/cache": "^5.2|^6.0", - "symfony/console": "^2.0.5|^3.0|^4.0|^5.0|^6.0", - "vimeo/psalm": "4.13.0" + "symfony/console": "^2.7|^3.0|^4.0|^5.0|^6.0", + "vimeo/psalm": "4.16.1" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -1238,7 +1165,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.2.0" + "source": "https://github.com/doctrine/dbal/tree/3.3.2" }, "funding": [ { @@ -1254,7 +1181,7 @@ "type": "tidelift" } ], - "time": "2021-11-26T21:00:12+00:00" + "time": "2022-02-05T16:33:45+00:00" }, { "name": "doctrine/deprecations", @@ -1486,16 +1413,16 @@ }, { "name": "doctrine/lexer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c" + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c", - "reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", "shasum": "" }, "require": { @@ -1503,7 +1430,7 @@ }, "require-dev": { "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "1.3", + "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", "vimeo/psalm": "^4.11" }, @@ -1542,7 +1469,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.2" + "source": "https://github.com/doctrine/lexer/tree/1.2.3" }, "funding": [ { @@ -1558,27 +1485,27 @@ "type": "tidelift" } ], - "time": "2022-01-12T08:27:12+00:00" + "time": "2022-02-28T11:07:21+00:00" }, { "name": "dompdf/dompdf", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "de4aad040737a89fae2129cdeb0f79c45513128d" + "reference": "60b704331479a69e9bcdb3496da2315b5c4f94fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/de4aad040737a89fae2129cdeb0f79c45513128d", - "reference": "de4aad040737a89fae2129cdeb0f79c45513128d", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/60b704331479a69e9bcdb3496da2315b5c4f94fd", + "reference": "60b704331479a69e9bcdb3496da2315b5c4f94fd", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "phenx/php-font-lib": "^0.5.2", - "phenx/php-svg-lib": "^0.3.3", + "phenx/php-font-lib": "^0.5.4", + "phenx/php-svg-lib": "^0.3.3 || ^0.4.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -1623,9 +1550,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v1.1.1" + "source": "https://github.com/dompdf/dompdf/tree/v1.2.0" }, - "time": "2021-11-24T00:45:04+00:00" + "time": "2022-02-07T13:02:10+00:00" }, { "name": "dragonmantank/cron-expression", @@ -2321,26 +2248,26 @@ }, { "name": "graham-campbell/manager", - "version": "v4.6.1", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Laravel-Manager.git", - "reference": "c5c89d02fd6125b121c58245caf4b918a413d4be" + "reference": "b4cafa6491b9c92ecf7ce17521580050a27b8308" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Laravel-Manager/zipball/c5c89d02fd6125b121c58245caf4b918a413d4be", - "reference": "c5c89d02fd6125b121c58245caf4b918a413d4be", + "url": "https://api.github.com/repos/GrahamCampbell/Laravel-Manager/zipball/b4cafa6491b9c92ecf7ce17521580050a27b8308", + "reference": "b4cafa6491b9c92ecf7ce17521580050a27b8308", "shasum": "" }, "require": { - "illuminate/contracts": "^5.5 || ^6.0 || ^7.0 || ^8.0", - "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0", + "illuminate/contracts": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0", "php": "^7.1.3 || ^8.0" }, "require-dev": { "graham-campbell/analyzer": "^2.4 || ^3.0", - "graham-campbell/testbench-core": "^3.2", + "graham-campbell/testbench-core": "^3.4", "mockery/mockery": "^1.3.1", "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.7" }, @@ -2375,7 +2302,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Laravel-Manager/issues", - "source": "https://github.com/GrahamCampbell/Laravel-Manager/tree/v4.6.1" + "source": "https://github.com/GrahamCampbell/Laravel-Manager/tree/v4.7.0" }, "funding": [ { @@ -2387,7 +2314,7 @@ "type": "tidelift" } ], - "time": "2021-11-21T14:34:20+00:00" + "time": "2022-01-24T01:59:19+00:00" }, { "name": "graham-campbell/result-type", @@ -2602,12 +2529,12 @@ } }, "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3126,16 +3053,16 @@ }, { "name": "laravel/framework", - "version": "v8.83.2", + "version": "v8.83.3", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "b91b3b5b39fbbdc763746f5714e08d50a4dd7857" + "reference": "b4ed222a188cca74ca9062296e525d26ae54a0ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/b91b3b5b39fbbdc763746f5714e08d50a4dd7857", - "reference": "b91b3b5b39fbbdc763746f5714e08d50a4dd7857", + "url": "https://api.github.com/repos/laravel/framework/zipball/b4ed222a188cca74ca9062296e525d26ae54a0ce", + "reference": "b4ed222a188cca74ca9062296e525d26ae54a0ce", "shasum": "" }, "require": { @@ -3295,7 +3222,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-02-22T15:10:17+00:00" + "time": "2022-03-03T15:14:29+00:00" }, { "name": "laravel/passport", @@ -3649,31 +3576,30 @@ }, { "name": "lcobucci/clock", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3" + "reference": "903513d28e85376a33385ebc601afd2ee69e5653" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/353d83fe2e6ae95745b16b3d911813df6a05bfb3", - "reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/903513d28e85376a33385ebc601afd2ee69e5653", + "reference": "903513d28e85376a33385ebc601afd2ee69e5653", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "php": "^8.0" }, "require-dev": { - "infection/infection": "^0.17", - "lcobucci/coding-standard": "^6.0", - "phpstan/extension-installer": "^1.0", + "infection/infection": "^0.25", + "lcobucci/coding-standard": "^8.0", + "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^0.12", "phpstan/phpstan-deprecation-rules": "^0.12", "phpstan/phpstan-phpunit": "^0.12", "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/php-code-coverage": "9.1.4", - "phpunit/phpunit": "9.3.7" + "phpunit/phpunit": "^9.5" }, "type": "library", "autoload": { @@ -3694,7 +3620,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/2.0.x" + "source": "https://github.com/lcobucci/clock/tree/2.1.0" }, "funding": [ { @@ -3706,7 +3632,7 @@ "type": "patreon" } ], - "time": "2020-08-27T18:56:02+00:00" + "time": "2021-10-31T21:32:07+00:00" }, { "name": "lcobucci/jwt", @@ -5226,12 +5152,12 @@ } }, "autoload": { - "psr-4": { - "JmesPath\\": "src/" - }, "files": [ "src/JmesPath.php" - ] + ], + "psr-4": { + "JmesPath\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6041,24 +5967,25 @@ }, { "name": "phenx/php-svg-lib", - "version": "0.3.4", + "version": "0.4.1", "source": { "type": "git", - "url": "https://github.com/PhenX/php-svg-lib.git", - "reference": "f627771eb854aa7f45f80add0f23c6c4d67ea0f2" + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "4498b5df7b08e8469f0f8279651ea5de9626ed02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/f627771eb854aa7f45f80add0f23c6c4d67ea0f2", - "reference": "f627771eb854aa7f45f80add0f23c6c4d67ea0f2", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/4498b5df7b08e8469f0f8279651ea5de9626ed02", + "reference": "4498b5df7b08e8469f0f8279651ea5de9626ed02", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "sabberworm/php-css-parser": "^8.3" + "ext-mbstring": "*", + "php": "^7.1 || ^7.2 || ^7.3 || ^7.4 || ^8.0", + "sabberworm/php-css-parser": "^8.4" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" }, "type": "library", "autoload": { @@ -6079,10 +6006,10 @@ "description": "A library to read, parse and export to PDF SVG files.", "homepage": "https://github.com/PhenX/php-svg-lib", "support": { - "issues": "https://github.com/PhenX/php-svg-lib/issues", - "source": "https://github.com/PhenX/php-svg-lib/tree/0.3.4" + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/0.4.1" }, - "time": "2021-10-18T02:13:32+00:00" + "time": "2022-03-07T12:52:04+00:00" }, { "name": "php-http/client-common", @@ -6229,16 +6156,16 @@ }, { "name": "php-http/httplug", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/php-http/httplug.git", - "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9" + "reference": "f640739f80dfa1152533976e3c112477f69274eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/httplug/zipball/191a0a1b41ed026b717421931f8d3bd2514ffbf9", - "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9", + "url": "https://api.github.com/repos/php-http/httplug/zipball/f640739f80dfa1152533976e3c112477f69274eb", + "reference": "f640739f80dfa1152533976e3c112477f69274eb", "shasum": "" }, "require": { @@ -6285,9 +6212,9 @@ ], "support": { "issues": "https://github.com/php-http/httplug/issues", - "source": "https://github.com/php-http/httplug/tree/master" + "source": "https://github.com/php-http/httplug/tree/2.3.0" }, - "time": "2020-07-13T15:43:23+00:00" + "time": "2022-02-21T09:52:22+00:00" }, { "name": "php-http/message", @@ -6689,15 +6616,15 @@ } }, "autoload": { - "psr-4": { - "PragmaRX\\Coollection\\Package\\": "src/package", - "PragmaRX\\Coollection\\Tests\\": "tests", - "IlluminateExtracted\\": "src/package/Support/IlluminateExtracted", - "IlluminateExtracted\\Tests\\": "tests/IlluminateExtracted" - }, "files": [ "src/package/Support/helpers.php" - ] + ], + "psr-4": { + "IlluminateExtracted\\": "src/package/Support/IlluminateExtracted", + "IlluminateExtracted\\Tests\\": "tests/IlluminateExtracted", + "PragmaRX\\Coollection\\Tests\\": "tests", + "PragmaRX\\Coollection\\Package\\": "src/package" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6752,13 +6679,13 @@ }, "type": "library", "autoload": { - "psr-4": { - "PragmaRX\\Countries\\Package\\": "src/package", - "PragmaRX\\Countries\\Update\\": "src/update" - }, "files": [ "src/package/Support/helpers.php" - ] + ], + "psr-4": { + "PragmaRX\\Countries\\Update\\": "src/update", + "PragmaRX\\Countries\\Package\\": "src/package" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7088,14 +7015,14 @@ } }, "autoload": { - "psr-4": { - "IlluminateAgnostic\\Arr\\": "src/", - "IlluminateAgnostic\\Arr\\Tests\\": "tests/" - }, "files": [ "src/Support/helpers.php", "src/Support/alias.php" - ] + ], + "psr-4": { + "IlluminateAgnostic\\Arr\\": "src/", + "IlluminateAgnostic\\Arr\\Tests\\": "tests/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7158,14 +7085,14 @@ } }, "autoload": { - "psr-4": { - "IlluminateAgnostic\\Collection\\": "src/", - "IlluminateAgnostic\\Collection\\Tests\\": "tests/" - }, "files": [ "src/Support/helpers.php", "src/Support/alias.php" - ] + ], + "psr-4": { + "IlluminateAgnostic\\Collection\\": "src/", + "IlluminateAgnostic\\Collection\\Tests\\": "tests/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7234,14 +7161,14 @@ } }, "autoload": { - "psr-4": { - "IlluminateAgnostic\\Str\\": "src/", - "IlluminateAgnostic\\Str\\Tests\\": "tests/" - }, "files": [ "src/Support/helpers.php", "src/Support/alias.php" - ] + ], + "psr-4": { + "IlluminateAgnostic\\Str\\": "src/", + "IlluminateAgnostic\\Str\\Tests\\": "tests/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7999,12 +7926,12 @@ } }, "autoload": { - "psr-4": { - "Ramsey\\Uuid\\": "src/" - }, "files": [ "src/functions.php" - ] + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8138,8 +8065,8 @@ "autoload": { "psr-4": { "Sabre\\DAV\\": "lib/DAV/", - "Sabre\\DAVACL\\": "lib/DAVACL/", "Sabre\\CalDAV\\": "lib/CalDAV/", + "Sabre\\DAVACL\\": "lib/DAVACL/", "Sabre\\CardDAV\\": "lib/CardDAV/" } }, @@ -8195,14 +8122,14 @@ }, "type": "library", "autoload": { - "psr-4": { - "Sabre\\Event\\": "lib/" - }, "files": [ "lib/coroutine.php", "lib/Loop/functions.php", "lib/Promise/functions.php" - ] + ], + "psr-4": { + "Sabre\\Event\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8490,13 +8417,13 @@ }, "type": "library", "autoload": { - "psr-4": { - "Sabre\\Xml\\": "lib/" - }, "files": [ "lib/Deserializer/functions.php", "lib/Serializer/functions.php" - ] + ], + "psr-4": { + "Sabre\\Xml\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8899,28 +8826,37 @@ }, { "name": "spomky-labs/cbor-php", - "version": "v2.0.1", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "9776578000be884cd7864eeb7c37a4ac92d8c995" + "reference": "28e2712cfc0b48fae661a48ffc6896d7abe83684" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/9776578000be884cd7864eeb7c37a4ac92d8c995", - "reference": "9776578000be884cd7864eeb7c37a4ac92d8c995", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/28e2712cfc0b48fae661a48ffc6896d7abe83684", + "reference": "28e2712cfc0b48fae661a48ffc6896d7abe83684", "shasum": "" }, "require": { "brick/math": "^0.8.15|^0.9.0", + "ext-mbstring": "*", "php": ">=7.3" }, "require-dev": { - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-beberlei-assert": "^0.12", - "phpstan/phpstan-deprecation-rules": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12" + "ekino/phpstan-banned-code": "^1.0", + "ext-json": "*", + "infection/infection": "^0.18|^0.25", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-beberlei-assert": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.12", + "roave/security-advisories": "dev-latest", + "symplify/easy-coding-standard": "^10.0" }, "suggest": { "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", @@ -8954,15 +8890,19 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/v2.0.1" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/v2.1.0" }, "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, { "url": "https://www.patreon.com/FlorentMorselli", "type": "patreon" } ], - "time": "2020-08-31T20:08:03+00:00" + "time": "2021-12-13T12:46:26+00:00" }, { "name": "stevebauman/location", @@ -9033,16 +8973,16 @@ }, { "name": "stripe/stripe-php", - "version": "v7.112.0", + "version": "v7.116.0", "source": { "type": "git", "url": "https://github.com/stripe/stripe-php.git", - "reference": "f5213ccb88795663f73841bc65f467a0e1e61180" + "reference": "7a39f594f213ed3f443a95adf769d1ecbc8393e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stripe/stripe-php/zipball/f5213ccb88795663f73841bc65f467a0e1e61180", - "reference": "f5213ccb88795663f73841bc65f467a0e1e61180", + "url": "https://api.github.com/repos/stripe/stripe-php/zipball/7a39f594f213ed3f443a95adf769d1ecbc8393e7", + "reference": "7a39f594f213ed3f443a95adf769d1ecbc8393e7", "shasum": "" }, "require": { @@ -9087,9 +9027,9 @@ ], "support": { "issues": "https://github.com/stripe/stripe-php/issues", - "source": "https://github.com/stripe/stripe-php/tree/v7.112.0" + "source": "https://github.com/stripe/stripe-php/tree/v7.116.0" }, - "time": "2022-01-25T19:42:36+00:00" + "time": "2022-03-02T15:51:15+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -9169,16 +9109,16 @@ }, { "name": "symfony/console", - "version": "v5.4.3", + "version": "v5.4.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a2a86ec353d825c75856c6fd14fac416a7bdb6b8" + "reference": "d8111acc99876953f52fe16d4c50eb60940d49ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a2a86ec353d825c75856c6fd14fac416a7bdb6b8", - "reference": "a2a86ec353d825c75856c6fd14fac416a7bdb6b8", + "url": "https://api.github.com/repos/symfony/console/zipball/d8111acc99876953f52fe16d4c50eb60940d49ad", + "reference": "d8111acc99876953f52fe16d4c50eb60940d49ad", "shasum": "" }, "require": { @@ -9248,7 +9188,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.3" + "source": "https://github.com/symfony/console/tree/v5.4.5" }, "funding": [ { @@ -9264,25 +9204,24 @@ "type": "tidelift" } ], - "time": "2022-01-26T16:28:35+00:00" + "time": "2022-02-24T12:45:35+00:00" }, { "name": "symfony/css-selector", - "version": "v5.4.3", + "version": "v6.0.3", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "b0a190285cd95cb019237851205b8140ef6e368e" + "reference": "1955d595c12c111629cc814d3f2a2ff13580508a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/b0a190285cd95cb019237851205b8140ef6e368e", - "reference": "b0a190285cd95cb019237851205b8140ef6e368e", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/1955d595c12c111629cc814d3f2a2ff13580508a", + "reference": "1955d595c12c111629cc814d3f2a2ff13580508a", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2" }, "type": "library", "autoload": { @@ -9314,7 +9253,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.3" + "source": "https://github.com/symfony/css-selector/tree/v6.0.3" }, "funding": [ { @@ -9330,29 +9269,29 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" + "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", + "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -9381,7 +9320,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.0" }, "funding": [ { @@ -9397,7 +9336,7 @@ "type": "tidelift" } ], - "time": "2021-07-12T14:48:14+00:00" + "time": "2021-11-01T23:48:49+00:00" }, { "name": "symfony/error-handler", @@ -9472,40 +9411,38 @@ }, { "name": "symfony/event-dispatcher", - "version": "v5.4.3", + "version": "v6.0.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d" + "reference": "6472ea2dd415e925b90ca82be64b8bc6157f3934" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dec8a9f58d20df252b9cd89f1c6c1530f747685d", - "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6472ea2dd415e925b90ca82be64b8bc6157f3934", + "reference": "6472ea2dd415e925b90ca82be64b8bc6157f3934", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2", + "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<5.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" + "symfony/stopwatch": "^5.4|^6.0" }, "suggest": { "symfony/dependency-injection": "", @@ -9537,7 +9474,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.3" }, "funding": [ { @@ -9553,24 +9490,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "66bea3b09be61613cd3b4043a65a8ec48cfa6d2a" + "reference": "aa5422287b75594b90ee9cd807caf8f0df491385" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/66bea3b09be61613cd3b4043a65a8ec48cfa6d2a", - "reference": "66bea3b09be61613cd3b4043a65a8ec48cfa6d2a", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/aa5422287b75594b90ee9cd807caf8f0df491385", + "reference": "aa5422287b75594b90ee9cd807caf8f0df491385", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "psr/event-dispatcher": "^1" }, "suggest": { @@ -9579,7 +9516,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -9616,7 +9553,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.0" }, "funding": [ { @@ -9632,7 +9569,7 @@ "type": "tidelift" } ], - "time": "2021-07-12T14:48:14+00:00" + "time": "2021-07-15T12:33:35+00:00" }, { "name": "symfony/finder", @@ -9699,32 +9636,29 @@ }, { "name": "symfony/http-client", - "version": "v5.4.3", + "version": "v6.0.5", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "a5a467b62dc91eb253db51a91a2c1977f611f60c" + "reference": "a8f87328930932c455cffd048f965d1223d91915" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/a5a467b62dc91eb253db51a91a2c1977f611f60c", - "reference": "a5a467b62dc91eb253db51a91a2c1977f611f60c", + "url": "https://api.github.com/repos/symfony/http-client/zipball/a8f87328930932c455cffd048f965d1223d91915", + "reference": "a8f87328930932c455cffd048f965d1223d91915", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-client-contracts": "^2.4", - "symfony/polyfill-php73": "^1.11", - "symfony/polyfill-php80": "^1.16", + "symfony/http-client-contracts": "^3", "symfony/service-contracts": "^1.0|^2|^3" }, "provide": { "php-http/async-client-implementation": "*", "php-http/client-implementation": "*", "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "2.4" + "symfony/http-client-implementation": "3.0" }, "require-dev": { "amphp/amp": "^2.5", @@ -9735,10 +9669,10 @@ "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4.13|^5.1.5|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0" + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -9766,7 +9700,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v5.4.3" + "source": "https://github.com/symfony/http-client/tree/v6.0.5" }, "funding": [ { @@ -9782,24 +9716,24 @@ "type": "tidelift" } ], - "time": "2022-01-22T06:53:01+00:00" + "time": "2022-02-27T08:47:28+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v2.5.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ec82e57b5b714dbb69300d348bd840b345e24166" + "reference": "265f03fed057044a8e4dc159aa33596d0f48ed3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ec82e57b5b714dbb69300d348bd840b345e24166", - "reference": "ec82e57b5b714dbb69300d348bd840b345e24166", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/265f03fed057044a8e4dc159aa33596d0f48ed3f", + "reference": "265f03fed057044a8e4dc159aa33596d0f48ed3f", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=8.0.2" }, "suggest": { "symfony/http-client-implementation": "" @@ -9807,7 +9741,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -9844,7 +9778,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.0.0" }, "funding": [ { @@ -9860,20 +9794,20 @@ "type": "tidelift" } ], - "time": "2021-11-03T09:24:47+00:00" + "time": "2021-11-03T13:44:55+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.4.3", + "version": "v5.4.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "ef409ff341a565a3663157d4324536746d49a0c7" + "reference": "34e89bc147633c0f9dd6caaaf56da3b806a21465" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ef409ff341a565a3663157d4324536746d49a0c7", - "reference": "ef409ff341a565a3663157d4324536746d49a0c7", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/34e89bc147633c0f9dd6caaaf56da3b806a21465", + "reference": "34e89bc147633c0f9dd6caaaf56da3b806a21465", "shasum": "" }, "require": { @@ -9917,7 +9851,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.3" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.6" }, "funding": [ { @@ -9933,20 +9867,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-03-05T21:03:43+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.4.4", + "version": "v5.4.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "49f40347228c773688a0488feea0175aa7f4d268" + "reference": "d41f29ae9af1b5f40c7ebcddf09082953229411d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/49f40347228c773688a0488feea0175aa7f4d268", - "reference": "49f40347228c773688a0488feea0175aa7f4d268", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d41f29ae9af1b5f40c7ebcddf09082953229411d", + "reference": "d41f29ae9af1b5f40c7ebcddf09082953229411d", "shasum": "" }, "require": { @@ -10029,7 +9963,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.4.4" + "source": "https://github.com/symfony/http-kernel/tree/v5.4.6" }, "funding": [ { @@ -10045,7 +9979,7 @@ "type": "tidelift" } ], - "time": "2022-01-29T18:08:07+00:00" + "time": "2022-03-05T21:14:51+00:00" }, { "name": "symfony/mime", @@ -10132,23 +10066,21 @@ }, { "name": "symfony/options-resolver", - "version": "v5.4.3", + "version": "v6.0.3", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8" + "reference": "51f7006670febe4cbcbae177cbffe93ff833250d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/cc1147cb11af1b43f503ac18f31aa3bec213aba8", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/51f7006670febe4cbcbae177cbffe93ff833250d", + "reference": "51f7006670febe4cbcbae177cbffe93ff833250d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2", + "symfony/deprecation-contracts": "^2.1|^3" }, "type": "library", "autoload": { @@ -10181,7 +10113,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.3" + "source": "https://github.com/symfony/options-resolver/tree/v6.0.3" }, "funding": [ { @@ -10197,11 +10129,11 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -10263,7 +10195,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" }, "funding": [ { @@ -10283,7 +10215,7 @@ }, { "name": "symfony/polyfill-iconv", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", @@ -10346,7 +10278,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-iconv/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.25.0" }, "funding": [ { @@ -10366,7 +10298,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -10427,7 +10359,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" }, "funding": [ { @@ -10447,7 +10379,7 @@ }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", @@ -10514,7 +10446,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.25.0" }, "funding": [ { @@ -10534,7 +10466,7 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -10601,7 +10533,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0" }, "funding": [ { @@ -10621,7 +10553,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -10685,7 +10617,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" }, "funding": [ { @@ -10705,7 +10637,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -10768,7 +10700,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" }, "funding": [ { @@ -10788,7 +10720,7 @@ }, { "name": "symfony/polyfill-php72", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", @@ -10844,7 +10776,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" }, "funding": [ { @@ -10864,7 +10796,7 @@ }, { "name": "symfony/polyfill-php73", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", @@ -10923,7 +10855,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0" }, "funding": [ { @@ -10943,16 +10875,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", "shasum": "" }, "require": { @@ -11006,7 +10938,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" }, "funding": [ { @@ -11022,11 +10954,11 @@ "type": "tidelift" } ], - "time": "2021-09-13T13:58:33+00:00" + "time": "2022-03-04T08:16:47+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -11085,7 +11017,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0" }, "funding": [ { @@ -11105,7 +11037,7 @@ }, { "name": "symfony/polyfill-uuid", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -11167,7 +11099,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.25.0" }, "funding": [ { @@ -11187,16 +11119,16 @@ }, { "name": "symfony/process", - "version": "v5.4.3", + "version": "v5.4.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "553f50487389a977eb31cf6b37faae56da00f753" + "reference": "95440409896f90a5f85db07a32b517ecec17fa4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/553f50487389a977eb31cf6b37faae56da00f753", - "reference": "553f50487389a977eb31cf6b37faae56da00f753", + "url": "https://api.github.com/repos/symfony/process/zipball/95440409896f90a5f85db07a32b517ecec17fa4c", + "reference": "95440409896f90a5f85db07a32b517ecec17fa4c", "shasum": "" }, "require": { @@ -11229,7 +11161,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.3" + "source": "https://github.com/symfony/process/tree/v5.4.5" }, "funding": [ { @@ -11245,7 +11177,7 @@ "type": "tidelift" } ], - "time": "2022-01-26T16:28:35+00:00" + "time": "2022-01-30T18:16:22+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -11427,22 +11359,21 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.0", + "version": "v2.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" + "reference": "d664541b99d6fb0247ec5ff32e87238582236204" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", - "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d664541b99d6fb0247ec5ff32e87238582236204", + "reference": "d664541b99d6fb0247ec5ff32e87238582236204", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1" + "psr/container": "^1.1" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -11453,7 +11384,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -11490,7 +11421,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v2.4.1" }, "funding": [ { @@ -11506,38 +11437,37 @@ "type": "tidelift" } ], - "time": "2021-11-04T16:48:04+00:00" + "time": "2021-11-04T16:37:19+00:00" }, { "name": "symfony/string", - "version": "v5.4.3", + "version": "v6.0.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" + "reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", - "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", + "url": "https://api.github.com/repos/symfony/string/zipball/522144f0c4c004c80d56fa47e40e17028e2eefc2", + "reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.0" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -11576,7 +11506,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.3" + "source": "https://github.com/symfony/string/tree/v6.0.3" }, "funding": [ { @@ -11592,20 +11522,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/translation", - "version": "v5.4.3", + "version": "v5.4.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "a9dd7403232c61e87e27fb306bbcd1627f245d70" + "reference": "a7ca9fdfffb0174209440c2ffa1dee228e15d95b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/a9dd7403232c61e87e27fb306bbcd1627f245d70", - "reference": "a9dd7403232c61e87e27fb306bbcd1627f245d70", + "url": "https://api.github.com/repos/symfony/translation/zipball/a7ca9fdfffb0174209440c2ffa1dee228e15d95b", + "reference": "a7ca9fdfffb0174209440c2ffa1dee228e15d95b", "shasum": "" }, "require": { @@ -11673,7 +11603,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.4.3" + "source": "https://github.com/symfony/translation/tree/v5.4.6" }, "funding": [ { @@ -11689,7 +11619,7 @@ "type": "tidelift" } ], - "time": "2022-01-07T00:28:17+00:00" + "time": "2022-03-02T12:56:28+00:00" }, { "name": "symfony/translation-contracts", @@ -11771,16 +11701,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.4.3", + "version": "v5.4.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "970a01f208bf895c5f327ba40b72288da43adec4" + "reference": "294e9da6e2e0dd404e983daa5aa74253d92c05d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/970a01f208bf895c5f327ba40b72288da43adec4", - "reference": "970a01f208bf895c5f327ba40b72288da43adec4", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/294e9da6e2e0dd404e983daa5aa74253d92c05d0", + "reference": "294e9da6e2e0dd404e983daa5aa74253d92c05d0", "shasum": "" }, "require": { @@ -11840,7 +11770,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.3" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.6" }, "funding": [ { @@ -11856,7 +11786,7 @@ "type": "tidelift" } ], - "time": "2022-01-17T16:30:37+00:00" + "time": "2022-03-02T12:42:23+00:00" }, { "name": "tedivm/jshrink", @@ -11943,13 +11873,6 @@ } }, "autoload": { - "psr-4": { - "Safe\\": [ - "lib/", - "deprecated/", - "generated/" - ] - }, "files": [ "deprecated/apc.php", "deprecated/libevent.php", @@ -12040,7 +11963,14 @@ "generated/yaz.php", "generated/zip.php", "generated/zlib.php" - ] + ], + "psr-4": { + "Safe\\": [ + "lib/", + "deprecated/", + "generated/" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -12348,12 +12278,12 @@ } }, "autoload": { - "psr-4": { - "Vluzrmos\\LanguageDetector\\": "src/" - }, "files": [ "src/Support/helpers.php" - ] + ], + "psr-4": { + "Vluzrmos\\LanguageDetector\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -12455,16 +12385,16 @@ }, { "name": "web-auth/cose-lib", - "version": "v3.3.9", + "version": "v3.3.12", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "ed172d2dc1a6b87b5c644c07c118cd30c1b3819b" + "reference": "efa6ec2ba4e840bc1316a493973c9916028afeeb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/ed172d2dc1a6b87b5c644c07c118cd30c1b3819b", - "reference": "ed172d2dc1a6b87b5c644c07c118cd30c1b3819b", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/efa6ec2ba4e840bc1316a493973c9916028afeeb", + "reference": "efa6ec2ba4e840bc1316a493973c9916028afeeb", "shasum": "" }, "require": { @@ -12502,7 +12432,7 @@ "RFC8152" ], "support": { - "source": "https://github.com/web-auth/cose-lib/tree/v3.3.9" + "source": "https://github.com/web-auth/cose-lib/tree/v3.3.12" }, "funding": [ { @@ -12514,20 +12444,20 @@ "type": "patreon" } ], - "time": "2021-05-02T19:57:09+00:00" + "time": "2021-12-04T12:13:35+00:00" }, { "name": "web-auth/metadata-service", - "version": "v3.3.9", + "version": "v3.3.12", "source": { "type": "git", "url": "https://github.com/web-auth/webauthn-metadata-service.git", - "reference": "8488d3a832a38cc81c670fce05de1e515c6e64b1" + "reference": "ef40d2b7b68c4964247d13fab52e2fa8dbd65246" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-metadata-service/zipball/8488d3a832a38cc81c670fce05de1e515c6e64b1", - "reference": "8488d3a832a38cc81c670fce05de1e515c6e64b1", + "url": "https://api.github.com/repos/web-auth/webauthn-metadata-service/zipball/ef40d2b7b68c4964247d13fab52e2fa8dbd65246", + "reference": "ef40d2b7b68c4964247d13fab52e2fa8dbd65246", "shasum": "" }, "require": { @@ -12571,7 +12501,7 @@ "webauthn" ], "support": { - "source": "https://github.com/web-auth/webauthn-metadata-service/tree/v3.3.9" + "source": "https://github.com/web-auth/webauthn-metadata-service/tree/v3.3.12" }, "funding": [ { @@ -12583,20 +12513,20 @@ "type": "patreon" } ], - "time": "2021-01-09T13:31:01+00:00" + "time": "2021-11-21T11:14:31+00:00" }, { "name": "web-auth/webauthn-lib", - "version": "v3.3.9", + "version": "v3.3.12", "source": { "type": "git", "url": "https://github.com/web-auth/webauthn-lib.git", - "reference": "04b98ee3d39cb79dad68a7c15c297c085bf66bfe" + "reference": "5ef9b21c8e9f8a817e524ac93290d08a9f065b33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/04b98ee3d39cb79dad68a7c15c297c085bf66bfe", - "reference": "04b98ee3d39cb79dad68a7c15c297c085bf66bfe", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/5ef9b21c8e9f8a817e524ac93290d08a9f065b33", + "reference": "5ef9b21c8e9f8a817e524ac93290d08a9f065b33", "shasum": "" }, "require": { @@ -12612,7 +12542,7 @@ "psr/log": "^1.1", "ramsey/uuid": "^3.8|^4.0", "spomky-labs/base64url": "^2.0", - "spomky-labs/cbor-php": "^1.1|^2.0", + "spomky-labs/cbor-php": "^1.0|^2.0", "symfony/process": "^3.0|^4.0|^5.0", "thecodingmachine/safe": "^1.1", "web-auth/cose-lib": "self.version", @@ -12653,7 +12583,7 @@ "webauthn" ], "support": { - "source": "https://github.com/web-auth/webauthn-lib/tree/v3.3.9" + "source": "https://github.com/web-auth/webauthn-lib/tree/v3.3.12" }, "funding": [ { @@ -12665,7 +12595,7 @@ "type": "patreon" } ], - "time": "2021-04-19T20:22:20+00:00" + "time": "2022-02-18T07:13:44+00:00" }, { "name": "web-token/jwt-core", @@ -13671,16 +13601,16 @@ }, { "name": "composer/composer", - "version": "2.2.1", + "version": "2.2.7", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "bbc265e16561ab8e0f5e7cac395ea72640251f0c" + "reference": "061d154dfdde157cbf453c4695e6af21c0e93903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/bbc265e16561ab8e0f5e7cac395ea72640251f0c", - "reference": "bbc265e16561ab8e0f5e7cac395ea72640251f0c", + "url": "https://api.github.com/repos/composer/composer/zipball/061d154dfdde157cbf453c4695e6af21c0e93903", + "reference": "061d154dfdde157cbf453c4695e6af21c0e93903", "shasum": "" }, "require": { @@ -13689,7 +13619,7 @@ "composer/pcre": "^1.0", "composer/semver": "^3.0", "composer/spdx-licenses": "^1.2", - "composer/xdebug-handler": "^2.0", + "composer/xdebug-handler": "^2.0 || ^3.0", "justinrainbow/json-schema": "^5.2.11", "php": "^5.3.2 || ^7.0 || ^8.0", "psr/log": "^1.0 || ^2.0", @@ -13750,7 +13680,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.2.1" + "source": "https://github.com/composer/composer/tree/2.2.7" }, "funding": [ { @@ -13766,7 +13696,7 @@ "type": "tidelift" } ], - "time": "2021-12-22T21:21:31+00:00" + "time": "2022-02-25T10:12:27+00:00" }, { "name": "composer/metadata-minifier", @@ -13837,6 +13767,79 @@ ], "time": "2021-04-07T13:37:33+00:00" }, + { + "name": "composer/package-versions-deprecated", + "version": "1.11.99.5", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7 || ^8" + }, + "replace": { + "ocramius/package-versions": "1.11.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-17T14:14:24+00:00" + }, { "name": "composer/pcre", "version": "1.0.1", @@ -14071,27 +14074,27 @@ }, { "name": "composer/xdebug-handler", - "version": "2.0.5", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" + "reference": "ced299686f41dce890debac69273b47ffe98a40c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", "shasum": "" }, "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + "symfony/phpunit-bridge": "^6.0" }, "type": "library", "autoload": { @@ -14117,7 +14120,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" }, "funding": [ { @@ -14133,7 +14136,7 @@ "type": "tidelift" } ], - "time": "2022-02-24T20:20:32+00:00" + "time": "2022-02-25T21:32:43+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -14174,29 +14177,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", + "doctrine/coding-standard": "^9", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" }, "type": "library", "autoload": { @@ -14223,7 +14227,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" }, "funding": [ { @@ -14239,7 +14243,7 @@ "type": "tidelift" } ], - "time": "2020-11-10T18:47:58+00:00" + "time": "2022-03-03T08:28:38+00:00" }, { "name": "fakerphp/faker", @@ -14623,12 +14627,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Zxing\\": "lib/" - }, "files": [ "lib/Common/customFunctions.php" - ] + ], + "psr-4": { + "Zxing\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -15035,25 +15039,29 @@ }, { "name": "myclabs/deep-copy", - "version": "1.10.2", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { @@ -15078,7 +15086,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" }, "funding": [ { @@ -15086,7 +15094,7 @@ "type": "tidelift" } ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { "name": "netresearch/jsonmapper", @@ -15435,22 +15443,22 @@ }, { "name": "orchestra/testbench", - "version": "v6.23.2", + "version": "v6.24.1", "source": { "type": "git", "url": "https://github.com/orchestral/testbench.git", - "reference": "4187adf0fbfd7a4f9758a23233d3dfd041153fed" + "reference": "7b6a225851f6c148a80e241af5cbd833c83e572c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench/zipball/4187adf0fbfd7a4f9758a23233d3dfd041153fed", - "reference": "4187adf0fbfd7a4f9758a23233d3dfd041153fed", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/7b6a225851f6c148a80e241af5cbd833c83e572c", + "reference": "7b6a225851f6c148a80e241af5cbd833c83e572c", "shasum": "" }, "require": { "laravel/framework": "^8.75", "mockery/mockery": "^1.4.4", - "orchestra/testbench-core": "^6.27.4", + "orchestra/testbench-core": "^6.28.1", "php": "^7.3 || ^8.0", "phpunit/phpunit": "^8.5.21 || ^9.5.10", "spatie/laravel-ray": "^1.26.2" @@ -15484,7 +15492,7 @@ ], "support": { "issues": "https://github.com/orchestral/testbench/issues", - "source": "https://github.com/orchestral/testbench/tree/v6.23.2" + "source": "https://github.com/orchestral/testbench/tree/v6.24.1" }, "funding": [ { @@ -15496,20 +15504,20 @@ "type": "liberapay" } ], - "time": "2021-12-23T00:22:47+00:00" + "time": "2022-02-08T12:57:17+00:00" }, { "name": "orchestra/testbench-core", - "version": "v6.27.4", + "version": "v6.28.1", "source": { "type": "git", "url": "https://github.com/orchestral/testbench-core.git", - "reference": "a7244cb4ad3fa452cd0b0371c52c94c9f24f4541" + "reference": "e66074e825e21b40b3433703dc3f76f2bfebebe0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/a7244cb4ad3fa452cd0b0371c52c94c9f24f4541", - "reference": "a7244cb4ad3fa452cd0b0371c52c94c9f24f4541", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/e66074e825e21b40b3433703dc3f76f2bfebebe0", + "reference": "e66074e825e21b40b3433703dc3f76f2bfebebe0", "shasum": "" }, "require": { @@ -15544,12 +15552,12 @@ } }, "autoload": { - "psr-4": { - "Orchestra\\Testbench\\": "src/" - }, "files": [ "src/helpers.php" - ] + ], + "psr-4": { + "Orchestra\\Testbench\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -15586,7 +15594,7 @@ "type": "liberapay" } ], - "time": "2021-12-23T00:07:34+00:00" + "time": "2022-02-08T12:50:35+00:00" }, { "name": "phar-io/manifest", @@ -15687,12 +15695,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Facebook\\WebDriver\\": "lib/" - }, "files": [ "lib/Exception/TimeoutException.php" - ] + ], + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -16006,16 +16014,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.13", + "version": "9.2.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8" + "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/deac8540cb7bd40b2b8cfa679b76202834fd04e8", - "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", "shasum": "" }, "require": { @@ -16071,7 +16079,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.13" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" }, "funding": [ { @@ -16079,7 +16087,7 @@ "type": "github" } ], - "time": "2022-02-23T17:02:38+00:00" + "time": "2022-03-07T09:28:20+00:00" }, { "name": "phpunit/php-file-iterator", @@ -16386,16 +16394,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.16", + "version": "9.5.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc" + "reference": "1b5856028273bfd855e60a887278857d872ec67a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5ff8c545a50226c569310a35f4fa89d79f1ddfdc", - "reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b5856028273bfd855e60a887278857d872ec67a", + "reference": "1b5856028273bfd855e60a887278857d872ec67a", "shasum": "" }, "require": { @@ -16473,7 +16481,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.16" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.18" }, "funding": [ { @@ -16485,7 +16493,7 @@ "type": "github" } ], - "time": "2022-02-23T17:10:58+00:00" + "time": "2022-03-08T06:52:28+00:00" }, { "name": "pimple/pimple", @@ -16542,16 +16550,16 @@ }, { "name": "psalm/plugin-laravel", - "version": "v1.5.1", + "version": "v1.5.3", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-laravel.git", - "reference": "183c230d330ce8b65fcd7f571083bfebc4f92d6d" + "reference": "902d217a1e777459ee8abe855abac1154280febd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-laravel/zipball/183c230d330ce8b65fcd7f571083bfebc4f92d6d", - "reference": "183c230d330ce8b65fcd7f571083bfebc4f92d6d", + "url": "https://api.github.com/repos/psalm/psalm-plugin-laravel/zipball/902d217a1e777459ee8abe855abac1154280febd", + "reference": "902d217a1e777459ee8abe855abac1154280febd", "shasum": "" }, "require": { @@ -16566,8 +16574,8 @@ "illuminate/routing": "^6.0 || ^8.0", "illuminate/support": "^6.0 || ^8.0", "illuminate/view": "^6.0 || ^8.0", - "orchestra/testbench": "^3.8 || ^4.0 || ^5.0 || ^6.0", - "php": "^7.3|^8", + "orchestra/testbench": "^3.8 || ^4.0 || ^5.0 || ^6.22 || ^7.0", + "php": "^7.3|^8.0", "vimeo/psalm": "^4.8.1" }, "require-dev": { @@ -16603,24 +16611,25 @@ } ], "description": "A Laravel plugin for Psalm", + "homepage": "https://github.com/psalm/psalm-plugin-laravel", "support": { "issues": "https://github.com/psalm/psalm-plugin-laravel/issues", - "source": "https://github.com/psalm/psalm-plugin-laravel/tree/v1.5.1" + "source": "https://github.com/psalm/psalm-plugin-laravel/tree/v1.5.3" }, - "time": "2021-07-19T18:16:35+00:00" + "time": "2022-03-04T17:28:25+00:00" }, { "name": "psy/psysh", - "version": "v0.11.1", + "version": "v0.11.2", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "570292577277f06f590635381a7f761a6cf4f026" + "reference": "7f7da640d68b9c9fec819caae7c744a213df6514" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/570292577277f06f590635381a7f761a6cf4f026", - "reference": "570292577277f06f590635381a7f761a6cf4f026", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/7f7da640d68b9c9fec819caae7c744a213df6514", + "reference": "7f7da640d68b9c9fec819caae7c744a213df6514", "shasum": "" }, "require": { @@ -16631,6 +16640,9 @@ "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, "require-dev": { "bamarni/composer-bin-plugin": "^1.2", "hoa/console": "3.17.05.02" @@ -16680,38 +16692,38 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.1" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.2" }, - "time": "2022-01-03T13:58:38+00:00" + "time": "2022-02-28T15:28:54+00:00" }, { "name": "react/promise", - "version": "v2.8.0", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4" + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4", + "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910", + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910", "shasum": "" }, "require": { "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, "type": "library", "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "React\\Promise\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -16720,7 +16732,23 @@ "authors": [ { "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], "description": "A lightweight implementation of CommonJS Promises/A for PHP", @@ -16730,9 +16758,19 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v2.8.0" + "source": "https://github.com/reactphp/promise/tree/v2.9.0" }, - "time": "2020-05-12T15:16:56+00:00" + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-02-11T10:27:51+00:00" }, { "name": "roave/security-advisories", @@ -16740,52 +16778,62 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "0488e161600117fc3a0d72397dad154729002f54" + "reference": "6c48c3048166dc4142a1a5f28a325faed3a578a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0488e161600117fc3a0d72397dad154729002f54", - "reference": "0488e161600117fc3a0d72397dad154729002f54", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/6c48c3048166dc4142a1a5f28a325faed3a578a3", + "reference": "6c48c3048166dc4142a1a5f28a325faed3a578a3", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", - "adodb/adodb-php": "<5.20.12", + "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", "akaunting/akaunting": "<2.1.13", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", "amazing/media2click": ">=1,<1.3.3", "amphp/artax": "<1.0.6|>=2,<2.0.6", "amphp/http": "<1.0.1", "amphp/http-client": ">=4,<4.4", + "anchorcms/anchor-cms": "<=0.12.7", "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2", + "area17/twill": "<1.2.5|>=2,<2.5.3", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", "aws/aws-sdk-php": ">=3,<3.2.1", "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", - "baserproject/basercms": "<=4.5", + "baserproject/basercms": "<4.5.4", "billz/raspap-webgui": "<=2.6.6", "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", "bolt/bolt": "<3.7.2", "bolt/core": "<4.1.13", + "bottelet/flarepoint": "<2.2.1", "brightlocal/phpwhois": "<=4.2.5", - "buddypress/buddypress": "<5.1.2", + "buddypress/buddypress": "<7.2.1", "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.5.18|>=3.6,<3.6.15|>=3.7,<3.7.7", + "cakephp/cakephp": "<4.0.6", + "cardgate/magento2": "<2.0.33", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", "centreon/centreon": "<20.10.7", "cesnet/simplesamlphp-module-proxystatistics": "<3.1", "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", + "codeigniter4/framework": "<4.1.9", "codiad/codiad": "<=2.8.4", - "composer/composer": "<1.10.22|>=2-alpha.1,<2.0.13", + "composer/composer": "<1.10.23|>=2-alpha.1,<2.1.9", + "concrete5/concrete5": "<9", + "concrete5/core": "<8.5.7", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|= 4.10.0", + "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", - "craftcms/cms": "<3.6.7", + "craftcms/cms": "<3.7.14", "croogo/croogo": "<3.0.7", "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", @@ -16794,20 +16842,22 @@ "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", - "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", "doctrine/doctrine-bundle": "<1.5.2", "doctrine/doctrine-module": "<=0.7.1", "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<14|>= 3.3.beta1, < 13.0.2", + "dolibarr/dolibarr": "<16|>= 3.3.beta1, < 13.0.2", "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "drupal/core": ">=7,<7.88|>=8,<9.2.13|>=9.3,<9.3.6", "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", "dweeves/magmi": "<=0.7.24", "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", "endroid/qr-code-bundle": "<3.4.2", - "enshrined/svg-sanitize": "<0.13.1", + "enshrined/svg-sanitize": "<0.15", "erusev/parsedown": "<1.7.2", "ether/logs": "<3.0.4", "ezsystems/demobundle": ">=5.4,<5.4.6.1", @@ -16815,17 +16865,18 @@ "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<=1.5.25", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<=1.3.1", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<=7.5.15.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.26", "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", - "facade/ignition": "<1.16.14|>=2,<2.4.2|>=2.5,<2.5.2", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", "feehi/cms": "<=2.1.1", "feehi/feehicms": "<=0.1.3", "firebase/php-jwt": "<2", @@ -16836,52 +16887,66 @@ "fooman/tcpdf": "<6.2.22", "forkcms/forkcms": "<=5.9.2", "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<6.5.1", + "francoisjacquet/rosariosis": "<8.1.1", "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "froala/wysiwyg-editor": "<3.2.7", "fuel/core": "<1.8.1", - "getgrav/grav": "<1.7.21", - "getkirby/cms": "<=3.5.6", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "getgrav/grav": "<1.7.31", + "getkirby/cms": "<3.5.8", "getkirby/panel": "<2.5.14", "gilacms/gila": "<=1.11.4", + "globalpayments/php-sdk": "<2", + "google/protobuf": "<3.15", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", "gree/jose": "<=2.2", "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<5.6.1", + "grumpydictator/firefly-iii": "<5.6.5", "guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1", "helloxz/imgurl": "<=2.31", + "hillelcoren/invoice-ninja": "<5.3.35", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", "ibexa/post-install": "<=1.0.4", - "icecoder/icecoder": "<=8", + "icecoder/icecoder": "<=8.1", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", - "illuminate/database": "<6.20.26|>=7,<8.40", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", - "illuminate/view": ">=7,<7.1.2", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "impresscms/impresscms": "<=1.4.2", "in2code/femanager": "<5.5.1|>=6,<6.3.1", "intelliants/subrion": "<=4.2.1", "ivankristianto/phpwhois": "<=4.3", - "james-heinrich/getid3": "<1.9.9", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "james-heinrich/getid3": "<1.9.21", "joomla/archive": "<1.1.10", "joomla/session": "<1.3.1", + "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", "kazist/phpwhois": "<=4.2.6", + "kevinpapst/kimai2": "<1.16.7", "kitodo/presentation": "<3.1.2", "klaviyo/magento2-extension": ">=1,<3", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", "laminas/laminas-http": "<2.14.2", - "laravel/framework": "<6.20.26|>=7,<8.40", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "latte/latte": "<2.10.8", "lavalite/cms": "<=5.8", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<0.18.3", "league/flysystem": "<1.1.4|>=2,<2.1.1", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", - "librenms/librenms": "<21.1", + "librenms/librenms": "<22.2.2", + "limesurvey/limesurvey": "<3.27.19", + "livehelperchat/livehelperchat": "<=3.91", "livewire/livewire": ">2.2.4,<2.2.6", "lms/routes": "<2.1.1", "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", @@ -16890,17 +16955,22 @@ "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", "marcwillmann/turn": "<0.3.3", - "mautic/core": "<4|= 2.13.1", + "mautic/core": "<4.2|= 2.13.1", "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "microweber/microweber": "<1.3", "miniorange/miniorange-saml": "<1.4.3", "mittwald/typo3_forum": "<1.2.1", + "modx/revolution": "<2.8", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<3.5.17|>=3.7,<3.7.9|>=3.8,<3.8.8|>=3.9,<3.9.5|>=3.10,<3.10.2", + "moodle/moodle": "<3.9.11|>=3.10-beta,<3.10.8|>=3.11,<3.11.5", + "mustache/mustache": ">=2,<2.14.1", "namshi/jose": "<2.2", + "neoan3-apps/template": "<1.1.1", "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", "nilsteampassnet/teampass": "<=2.1.27.36", @@ -16909,17 +16979,17 @@ "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "october/backend": "<1.1.2", "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", - "october/october": ">=1.0.319,<1.0.466", + "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<1.0.472|>=1.1.1,<1.1.5", + "october/system": "<1.0.475|>=1.1,<1.1.11|>=2,<2.1.27", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", "opencart/opencart": "<=3.0.3.2", "openid/php-openid": "<2.3", "openmage/magento-lts": "<19.4.15|>=20,<20.0.13", "orchid/platform": ">=9,<9.4.4", - "oro/crm": ">=1.7,<1.7.4", - "oro/platform": ">=1.7,<1.7.4", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8", "padraic/humbug_get_contents": "<1.1.2", "pagarme/pagarme-php": ">=0,<3", "pagekit/pagekit": "<=1.0.18", @@ -16927,53 +16997,62 @@ "passbolt/passbolt_api": "<2.11", "paypal/merchant-sdk-php": "<3.12", "pear/archive_tar": "<1.4.14", + "pear/crypt_gpg": "<1.6.7", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", "phanan/koel": "<5.1.4", "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<4.9.6|>=5,<5.0.3", + "phpmyadmin/phpmyadmin": "<4.9.8|>=5,<5.0.3|>=5.1,<5.1.2", "phpoffice/phpexcel": "<1.8.2", "phpoffice/phpspreadsheet": "<1.16", "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpservermon/phpservermon": "<=3.5.2", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", - "pimcore/pimcore": "<10.1.3", - "pocketmine/pocketmine-mp": "<3.15.4", + "pimcore/pimcore": "<10.3.2", + "pocketmine/pocketmine-mp": "<4.0.7", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", "prestashop/contactform": ">1.0.1,<4.3", "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": ">=1.7,<=1.7.8.2", "prestashop/productcomments": ">=4,<4.2.1", "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<0.7.19|>=1-rc.0,<=1-rc.6", + "pterodactyl/panel": "<1.7", + "ptrofimov/beanstalk_console": "<1.7.14", "pusher/pusher-php-server": "<2.2.1", "pwweb/laravel-core": "<=0.3.6-beta", "rainlab/debugbar-plugin": "<3.1", + "remdex/livehelperchat": "<3.93", "rmccue/requests": ">=1.6,<1.8", "robrichards/xmlseclibs": "<3.0.4", + "rudloff/alltube": "<3.0.2", + "s-cart/s-cart": "<6.7.2", "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/core": "<=6.4.3", - "shopware/platform": "<=6.4.3", + "shopware/core": "<=6.4.6", + "shopware/platform": "<=6.4.6", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<5.6.10", - "showdoc/showdoc": "<=2.9.8", - "silverstripe/admin": ">=1.0.3,<1.0.4|>=1.1,<1.1.1", + "shopware/shopware": "<5.7.7", + "showdoc/showdoc": "<=2.10.2", + "silverstripe/admin": ">=1,<1.8.1", "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.7.4", - "silverstripe/graphql": "<=3.5|>=4-alpha.1,<4-alpha.2", + "silverstripe/framework": "<4.10.1", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", "silverstripe/subsites": ">=2,<2.1.1", @@ -16985,20 +17064,23 @@ "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", "simplito/elliptic-php": "<1.0.6", "slim/slim": "<2.6", - "smarty/smarty": "<3.1.39", + "smarty/smarty": "<3.1.43|>=4,<4.0.3", + "snipe/snipe-it": "<5.3.11", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", + "spipu/html2pdf": "<5.2.4", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", - "ssddanbrown/bookstack": "<0.29.2", + "ssddanbrown/bookstack": "<21.12.1", "stormpath/sdk": ">=0,<9.9.99", "studio-42/elfinder": "<2.1.59", "subrion/cms": "<=4.2.1", - "sulu/sulu": "<1.6.41|>=2,<2.0.10|>=2.1,<2.1.1", + "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", "swiftmailer/swiftmailer": ">=4,<5.4.5", "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", "sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", "sylius/sylius": "<1.6.9|>=1.7,<1.7.9|>=1.8,<1.8.3|>=1.9,<1.9.5", "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", @@ -17009,9 +17091,9 @@ "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", - "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5", + "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", "symfony/mime": ">=4.3,<4.3.8", @@ -17021,13 +17103,13 @@ "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", - "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11|>=5.3,<5.3.12", "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8|>=5.3,<5.3.2", - "symfony/serializer": ">=2,<2.0.11", - "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.24|>=5,<5.2.9|>=5.3,<5.3.2", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.35|>=5,<5.3.12|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3", "symfony/translation": ">=2,<2.0.17", "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", @@ -17036,18 +17118,21 @@ "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", "tecnickcom/tcpdf": "<6.2.22", + "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", + "tinymce/tinymce": "<5.10", "titon/framework": ">=0,<9.9.99", + "topthink/framework": "<6.0.9", "topthink/think": "<=6.0.9", "topthink/thinkphp": "<=3.2.3", - "tribalsystems/zenario": "<8.8.53370", + "tribalsystems/zenario": "<9.2.55826", "truckersmp/phpwhois": "<=4.3.1", - "twig/twig": "<1.38|>=2,<2.7", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.3.2", + "twig/twig": "<1.38|>=2,<2.14.11|>=3,<3.3.8", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5", "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", - "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<=7.6.52|>=8,<=8.7.41|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.3.2", + "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<=7.6.52|>=8,<=8.7.41|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5", "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", @@ -17055,16 +17140,20 @@ "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", + "unisharp/laravel-filemanager": "<=2.3", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", "vanilla/safecurl": "<0.9.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", "vrana/adminer": "<4.7.9", "wallabag/tcpdf": "<6.2.22", + "wanglelecc/laracms": "<=1.0.3", "web-auth/webauthn-framework": ">=3.3,<3.3.4", "webcoast/deferred-image-processing": "<1.0.2", "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", "wp-cli/wp-cli": "<2.5", + "yetiforce/yetiforce-crm": "<=6.3", "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", "yiisoft/yii": ">=1.1.14,<1.1.15", @@ -17137,7 +17226,7 @@ "type": "tidelift" } ], - "time": "2021-09-30T18:03:50+00:00" + "time": "2022-03-05T18:49:45+00:00" }, { "name": "sebastian/cli-parser", @@ -18278,41 +18367,43 @@ }, { "name": "spatie/laravel-ray", - "version": "1.26.5", + "version": "1.29.4", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ray.git", - "reference": "857d8fe465dbc025cbeb2735fe690ff9496f5f98" + "reference": "3cace74c812469e6e569dacffc46653457f9c2cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/857d8fe465dbc025cbeb2735fe690ff9496f5f98", - "reference": "857d8fe465dbc025cbeb2735fe690ff9496f5f98", + "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/3cace74c812469e6e569dacffc46653457f9c2cc", + "reference": "3cace74c812469e6e569dacffc46653457f9c2cc", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/contracts": "^7.20|^8.19", - "illuminate/database": "^7.20|^8.19", - "illuminate/queue": "^7.20|^8.19", - "illuminate/support": "^7.20|^8.19", + "illuminate/contracts": "^7.20|^8.19|^9.0", + "illuminate/database": "^7.20|^8.19|^9.0", + "illuminate/queue": "^7.20|^8.19|^9.0", + "illuminate/support": "^7.20|^8.19|^9.0", "php": "^7.3|^8.0", "spatie/backtrace": "^1.0", - "spatie/ray": "^1.27.1", + "spatie/ray": "^1.33", "symfony/stopwatch": "4.2|^5.1|^6.0", "zbateson/mail-mime-parser": "^1.3.1|^2.0" }, "require-dev": { - "facade/ignition": "^2.5", "guzzlehttp/guzzle": "^7.3", - "laravel/framework": "^7.20|^8.19", - "orchestra/testbench-core": "^5.0|^6.0", + "laravel/framework": "^7.20|^8.19|^9.0", + "orchestra/testbench-core": "^5.0|^6.0|^7.0", "phpstan/phpstan": "^0.12.93", "phpunit/phpunit": "^9.3", "spatie/phpunit-snapshot-assertions": "^4.2" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.29.x-dev" + }, "laravel": { "providers": [ "Spatie\\LaravelRay\\RayServiceProvider" @@ -18344,7 +18435,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-ray/issues", - "source": "https://github.com/spatie/laravel-ray/tree/1.26.5" + "source": "https://github.com/spatie/laravel-ray/tree/1.29.4" }, "funding": [ { @@ -18356,20 +18447,20 @@ "type": "other" } ], - "time": "2021-12-21T13:51:47+00:00" + "time": "2022-02-22T15:18:57+00:00" }, { "name": "spatie/ray", - "version": "1.32.2", + "version": "1.34.1", "source": { "type": "git", "url": "https://github.com/spatie/ray.git", - "reference": "c8534bcd14528a721c246ebc289d3cb480468431" + "reference": "4090df9fedf83ef6315e85db1e81f54c14e119c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ray/zipball/c8534bcd14528a721c246ebc289d3cb480468431", - "reference": "c8534bcd14528a721c246ebc289d3cb480468431", + "url": "https://api.github.com/repos/spatie/ray/zipball/4090df9fedf83ef6315e85db1e81f54c14e119c7", + "reference": "4090df9fedf83ef6315e85db1e81f54c14e119c7", "shasum": "" }, "require": { @@ -18383,7 +18474,7 @@ "symfony/var-dumper": "^4.2|^5.1|^6.0" }, "require-dev": { - "illuminate/support": "6.x|^8.18", + "illuminate/support": "6.x|^8.18|^9.0", "nesbot/carbon": "^2.43", "phpstan/phpstan": "^0.12.92", "phpunit/phpunit": "^9.5", @@ -18392,12 +18483,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Spatie\\Ray\\": "src" - }, "files": [ "src/helpers.php" - ] + ], + "psr-4": { + "Spatie\\Ray\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -18419,7 +18510,7 @@ ], "support": { "issues": "https://github.com/spatie/ray/issues", - "source": "https://github.com/spatie/ray/tree/1.32.2" + "source": "https://github.com/spatie/ray/tree/1.34.1" }, "funding": [ { @@ -18431,7 +18522,7 @@ "type": "other" } ], - "time": "2021-12-20T18:53:49+00:00" + "time": "2022-03-03T15:02:29+00:00" }, { "name": "symfony/debug", @@ -18503,22 +18594,22 @@ }, { "name": "symfony/filesystem", - "version": "v5.3.4", + "version": "v6.0.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32" + "reference": "52b888523545b0b4049ab9ce48766802484d7046" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32", - "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/52b888523545b0b4049ab9ce48766802484d7046", + "reference": "52b888523545b0b4049ab9ce48766802484d7046", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.8" }, "type": "library", "autoload": { @@ -18546,7 +18637,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.3.4" + "source": "https://github.com/symfony/filesystem/tree/v6.0.6" }, "funding": [ { @@ -18562,25 +18653,25 @@ "type": "tidelift" } ], - "time": "2021-07-21T12:40:44+00:00" + "time": "2022-03-02T12:58:14+00:00" }, { "name": "symfony/stopwatch", - "version": "v5.3.4", + "version": "v6.0.5", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "b24c6a92c6db316fee69e38c80591e080e41536c" + "reference": "f2c1780607ec6502f2121d9729fd8150a655d337" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b24c6a92c6db316fee69e38c80591e080e41536c", - "reference": "b24c6a92c6db316fee69e38c80591e080e41536c", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f2c1780607ec6502f2121d9729fd8150a655d337", + "reference": "f2c1780607ec6502f2121d9729fd8150a655d337", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1.0|^2" + "php": ">=8.0.2", + "symfony/service-contracts": "^1|^2|^3" }, "type": "library", "autoload": { @@ -18608,7 +18699,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.3.4" + "source": "https://github.com/symfony/stopwatch/tree/v6.0.5" }, "funding": [ { @@ -18624,20 +18715,20 @@ "type": "tidelift" } ], - "time": "2021-07-10T08:58:57+00:00" + "time": "2022-02-21T17:15:17+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.0", + "version": "v5.4.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "034ccc0994f1ae3f7499fa5b1f2e75d5e7a94efc" + "reference": "e80f87d2c9495966768310fc531b487ce64237a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/034ccc0994f1ae3f7499fa5b1f2e75d5e7a94efc", - "reference": "034ccc0994f1ae3f7499fa5b1f2e75d5e7a94efc", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", + "reference": "e80f87d2c9495966768310fc531b487ce64237a2", "shasum": "" }, "require": { @@ -18683,7 +18774,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.0" + "source": "https://github.com/symfony/yaml/tree/v5.4.3" }, "funding": [ { @@ -18699,7 +18790,7 @@ "type": "tidelift" } ], - "time": "2021-11-28T15:25:38+00:00" + "time": "2022-01-26T16:32:32+00:00" }, { "name": "thecodingmachine/phpstan-safe-rule", @@ -18967,16 +19058,16 @@ }, { "name": "zbateson/mail-mime-parser", - "version": "2.1.1", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/zbateson/mail-mime-parser.git", - "reference": "b969a8a72106dcdaa9ac4b19bb2e6b22d3fc5584" + "reference": "24955de7ec352b3258c1d4551efd21202cb8710c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/b969a8a72106dcdaa9ac4b19bb2e6b22d3fc5584", - "reference": "b969a8a72106dcdaa9ac4b19bb2e6b22d3fc5584", + "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/24955de7ec352b3258c1d4551efd21202cb8710c", + "reference": "24955de7ec352b3258c1d4551efd21202cb8710c", "shasum": "" }, "require": { @@ -19036,7 +19127,7 @@ "type": "github" } ], - "time": "2021-12-08T20:21:28+00:00" + "time": "2022-02-22T21:35:59+00:00" }, { "name": "zbateson/mb-wrapper", diff --git a/config/monica.php b/config/monica.php index 855cd170452..c1b755fcc8d 100644 --- a/config/monica.php +++ b/config/monica.php @@ -284,4 +284,26 @@ */ 'export_size' => (int) env('EXPORT_SIZE', 5), + /* + |-------------------------------------------------------------------------- + | Licence key server + |-------------------------------------------------------------------------- + | + | When REQUIRES_SUBSCRIPTION is set to true, we need to check if the user + | has a valid licence key to unlock paid features. Licence keys are managed + | on our own customer portal. + | + */ + 'customer_portal_url' => env('CUSTOMER_PORTAL_URL', ''), + + /* + |-------------------------------------------------------------------------- + | Licence key encryption key + |-------------------------------------------------------------------------- + | + | All licence keys are encrypted with this key on the customer portal when + | the key is generated. + | + */ + 'licence_key_encryption_key' => env('LICENCE_KEY_ENCRYPTION_KEY', null), ]; diff --git a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php new file mode 100644 index 00000000000..7a8ed1c586c --- /dev/null +++ b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php @@ -0,0 +1,36 @@ +string('licence_key')->after('uuid')->nullable(); + $table->datetime('valid_until_at')->after('licence_key')->nullable(); + $table->string('purchaser_email')->after('valid_until_at')->nullable(); + $table->string('frequency')->after('purchaser_email')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function (Blueprint $table) { + $table->dropColumn('licence_keys'); + $table->dropColumn('valid_until_at'); + }); + } +} diff --git a/package.json b/package.json index 42c3097bcfc..5a2b813d408 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "composer update": "COMPOSER_MEMORY_LIMIT=-1 composer update" }, "engines": { - "node": "16.x", + "node": "17.x", "yarn": "1.22.x" }, "devDependencies": { diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 503ccdff15e..4a262818f73 100644 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -217,7 +217,7 @@ 'subscriptions_account_free_plan_benefits_support' => 'Support the project in the long run, so we can introduce more great features.', 'subscriptions_account_upgrade' => 'Upgrade your account', 'subscriptions_account_upgrade_title' => 'Upgrade Monica today and have more meaningful relationships.', - 'subscriptions_account_upgrade_choice' => 'Pick a plan below and join over :customers persons who upgraded their Monica.', + 'subscriptions_account_upgrade_choice' => 'Monica requires a licence key to be completely functional.', 'subscriptions_account_update_title' => 'Update Monica subscription', 'subscriptions_account_update_description' => 'You can change your subscription’s frequency here.', 'subscriptions_account_update_information' => 'You will be billed immediately for the new amount. Your subscription will extend to the new period, depending on your choice.', @@ -263,7 +263,7 @@ 'subscriptions_pdf_title' => 'Your :name monthly subscription', 'subscriptions_plan_frequency_year' => ':amount / year', 'subscriptions_plan_frequency_month' => ':amount / month', - 'subscriptions_plan_choose' => 'Choose this plan', + 'subscriptions_plan_choose' => 'Get your licence key', 'subscriptions_plan_year_title' => 'Pay annually', 'subscriptions_plan_year_bonus' => 'Peace of mind for a whole year', 'subscriptions_plan_month_title' => 'Pay monthly', @@ -272,6 +272,8 @@ 'subscriptions_plan_include2' => 'Unlimited number of contacts • Unlimited number of users • Reminders by email • Import with vCard • Personalization of the contact sheet', 'subscriptions_plan_include3' => '100% of the profits go the development of this great open source project.', 'subscriptions_help_title' => 'Additional details you may be curious about', + 'subscriptions_help_licencekey_title' => 'What is a licence key?', + 'subscriptions_help_licencekey_desc' => 'A licence key is an unique identifier that you will get once you purchase a plan. It will be used to unlock all the paid features in your account. Licence keys are managed on https://customers.monicahq.com and you will need to create a new account on this site to get your licence key, that you will need to paste here.', 'subscriptions_help_opensource_title' => 'What is an open source project?', 'subscriptions_help_opensource_desc' => 'Monica is an open source project. This means it is built by a community who wants to build a great tool for the greater good. Being open source means the code is publicly available on GitHub, and everyone can inspect it, modify it or enhance it. All the money we raise is dedicated to building better features, paying for more powerful servers, and paying other costs. Thanks for your help. We couldn’t do it without you.', 'subscriptions_help_limits_title' => 'Is there a limit to the number of contacts we can have on the free plan?', @@ -280,6 +282,11 @@ 'subscriptions_help_discounts_desc' => 'We do! Monica is free for students, and free for non-profits and charities. Just contact the support with a proof of your status and we’ll apply this special status in your account.', 'subscriptions_help_change_title' => 'What if I change my mind?', 'subscriptions_help_change_desc' => 'You can cancel anytime, no questions asked, and all by yourself – no need to contact support. However, you will not be refunded for the current period.', + 'subscriptions_licence_key_does_not_exist' => 'The licence key does not appear to exist in our system. Please try again.', + 'subscriptions_licence_key_invalid' => 'This licence key is not valid anymore. Please renew your licence.', + 'subscriptions_licence_key_problem' => 'There is a problem with the system.', + 'subscriptions_licence_key_frequency_monthly' => 'Monthly', + 'subscriptions_licence_key_frequency_annual' => 'Annual', 'stripe_error_card' => 'Your card was declined. Decline message is: :message', 'stripe_error_api_connection' => 'Network communication with Stripe failed. Try again later.', diff --git a/resources/views/settings/subscriptions/account.blade.php b/resources/views/settings/subscriptions/account.blade.php index ecf9e3678e3..f61e7bf95f9 100644 --- a/resources/views/settings/subscriptions/account.blade.php +++ b/resources/views/settings/subscriptions/account.blade.php @@ -33,13 +33,11 @@
-
+

{{ trans('settings.subscriptions_account_current_plan') }}

-

{{ trans('settings.subscriptions_account_current_paid_plan', ['name' => $planInformation['name']]) }}

- - @include('partials.subscription') +

{{ trans('settings.subscriptions_account_current_paid_plan', ['name' => $planInformation]) }}

@@ -50,15 +48,12 @@
- {!! trans('settings.subscriptions_account_next_billing', ['date' => $planInformation['nextBillingDate']]) !!} -
-
- {!! trans('settings.subscriptions_account_bill_' . $planInformation['type'], ['price' => $planInformation['friendlyPrice']]) !!} + {!! trans('settings.subscriptions_account_next_billing', ['date' => $nextBillingDate]) !!}
@@ -76,7 +71,7 @@
- - {{-- Only display invoices if the subscription exists or existed --}} - @if ($hasInvoices) -
-

{{ trans('settings.subscriptions_account_invoices') }}

- -
- @endif -
diff --git a/resources/views/settings/subscriptions/blank.blade.php b/resources/views/settings/subscriptions/blank.blade.php index 266b52bdc5d..318854ee7eb 100644 --- a/resources/views/settings/subscriptions/blank.blade.php +++ b/resources/views/settings/subscriptions/blank.blade.php @@ -28,13 +28,13 @@
-
+

{{ trans('settings.subscriptions_account_upgrade_title') }}

-

{{ trans('settings.subscriptions_account_upgrade_choice', ['customers' => $numberOfCustomers]) }}

+

{{ trans('settings.subscriptions_account_upgrade_choice') }}

-
+

{{ trans('settings.subscriptions_account_payment') }}

@@ -43,7 +43,7 @@

{{ trans('settings.subscriptions_plan_year_title') }}

- {{ trans('settings.subscriptions_plan_choose') }} + {{ trans('settings.subscriptions_plan_choose') }}

{{ trans('settings.subscriptions_plan_frequency_year', ['amount' => \App\Helpers\InstanceHelper::getPlanInformationFromConfig('annual')['friendlyPrice']]) }} @@ -68,7 +68,7 @@

{{ trans('settings.subscriptions_plan_month_title') }}

- {{ trans('settings.subscriptions_plan_choose') }} + {{ trans('settings.subscriptions_plan_choose') }}

{{ trans('settings.subscriptions_plan_frequency_month', ['amount' => \App\Helpers\InstanceHelper::getPlanInformationFromConfig('monthly')['friendlyPrice']]) }} @@ -90,13 +90,36 @@

-

{{ trans('settings.subscriptions_plan_include1') }}

+ + +

{{ trans('settings.subscriptions_plan_include1') }}

{{ trans('settings.subscriptions_plan_include2') }}

{{ trans('settings.subscriptions_plan_include3') }}

+ +
+ +

Do you have your licence key?

+ + @include('partials.errors') + +
+ @csrf + +
+ + +
+
+
+
+

{{ trans('settings.subscriptions_help_title') }}

+

{{ trans('settings.subscriptions_help_licencekey_title') }}

+

{{ trans('settings.subscriptions_help_licencekey_desc') }}

+

{{ trans('settings.subscriptions_help_opensource_title') }}

{{ trans('settings.subscriptions_help_opensource_desc') }}

diff --git a/resources/views/settings/subscriptions/success.blade.php b/resources/views/settings/subscriptions/success.blade.php index b35674160d3..31fcd39dcdb 100644 --- a/resources/views/settings/subscriptions/success.blade.php +++ b/resources/views/settings/subscriptions/success.blade.php @@ -14,7 +14,7 @@ {{ trans('app.breadcrumb_dashboard') }}
  • - {{ trans('app.breadcrumb_settings') }} + {{ trans('app.breadcrumb_settings') }}
  • {{ trans('app.breadcrumb_settings_subscriptions') }} diff --git a/routes/web.php b/routes/web.php index 126473ebbe1..50c6e1c40e8 100644 --- a/routes/web.php +++ b/routes/web.php @@ -272,6 +272,8 @@ Route::name('subscriptions.')->group(function () { Route::get('/settings/subscriptions', 'Settings\\SubscriptionsController@index')->name('index'); + Route::post('/settings/subscriptions', 'Settings\\SubscriptionsController@store')->name('store'); + Route::get('/settings/subscriptions/upgrade', 'Settings\\SubscriptionsController@upgrade')->name('upgrade'); Route::get('/settings/subscriptions/upgrade/success', 'Settings\\SubscriptionsController@upgradeSuccess')->name('upgrade.success'); Route::get('/settings/subscriptions/update', 'Settings\\SubscriptionsController@update')->name('update'); diff --git a/tests/Feature/AccountSubscriptionTest.php b/tests/Feature/AccountSubscriptionTest.php index 74e8080be0f..155524fd718 100644 --- a/tests/Feature/AccountSubscriptionTest.php +++ b/tests/Feature/AccountSubscriptionTest.php @@ -156,22 +156,6 @@ public function test_it_get_the_plan_name() $this->assertEquals('Annual', $user->account->getSubscribedPlanName()); } - public function test_it_throw_an_error_on_cancel() - { - $user = $this->signin(); - - factory(Subscription::class)->create([ - 'account_id' => $user->account_id, - 'name' => 'Annual', - 'stripe_plan' => 'annual', - 'stripe_id' => 'test', - 'quantity' => 1, - ]); - - $this->expectException(\App\Exceptions\StripeException::class); - $user->account->subscriptionCancel(); - } - public function test_it_get_subscription_page() { $user = $this->signin(); diff --git a/tests/Unit/Helpers/InstanceHelperTest.php b/tests/Unit/Helpers/InstanceHelperTest.php index be1cfb90eb2..a908596da64 100644 --- a/tests/Unit/Helpers/InstanceHelperTest.php +++ b/tests/Unit/Helpers/InstanceHelperTest.php @@ -14,19 +14,6 @@ class InstanceHelperTest extends TestCase { use DatabaseTransactions; - /** @test */ - public function it_gets_the_number_of_paid_subscribers() - { - factory(Account::class)->create(['stripe_id' => 'id292839']); - factory(Account::class)->create(); - factory(Account::class)->create(['stripe_id' => 'id2sdf92839']); - - $this->assertEquals( - 2, - InstanceHelper::getNumberOfPaidSubscribers() - ); - } - /** @test */ public function it_fetches_the_monthly_plan_information() { diff --git a/tests/Unit/Models/AccountTest.php b/tests/Unit/Models/AccountTest.php index f9b2d053da6..3b858e2fae2 100644 --- a/tests/Unit/Models/AccountTest.php +++ b/tests/Unit/Models/AccountTest.php @@ -27,6 +27,7 @@ use App\Models\Account\ActivityTypeCategory; use App\Models\Relationship\RelationshipType; use App\Models\Relationship\RelationshipTypeGroup; +use Carbon\Carbon; use Illuminate\Foundation\Testing\DatabaseTransactions; class AccountTest extends FeatureTestCase @@ -277,6 +278,7 @@ public function user_is_subscribed_returns_false_if_not_subcribed() { $account = factory(Account::class)->make([ 'has_access_to_paid_version_for_free' => false, + 'licence_key' => null, ]); $this->assertEquals( @@ -286,19 +288,14 @@ public function user_is_subscribed_returns_false_if_not_subcribed() } /** @test */ - public function user_is_subscribed_returns_true_if_monthly_plan_is_set() + public function user_is_subscribed_returns_true_if_there_is_a_valid_licence_key() { - $account = factory(Account::class)->create(); - - $plan = factory(\Laravel\Cashier\Subscription::class)->create([ - 'account_id' => $account->id, - 'stripe_plan' => 'chandler_5', - 'stripe_id' => 'sub_C0R444pbxddhW7', - 'name' => 'fakePlan', + Carbon::setTestNow(Carbon::create(2018, 1, 1)); + $account = factory(Account::class)->create([ + 'licence_key' => '123', + 'valid_until_at' => '2022-01-01', ]); - config(['monica.paid_plan_monthly_friendly_name' => 'fakePlan']); - $this->assertEquals( true, $account->isSubscribed() @@ -306,30 +303,14 @@ public function user_is_subscribed_returns_true_if_monthly_plan_is_set() } /** @test */ - public function user_is_subscribed_returns_true_if_annual_plan_is_set() + public function user_is_subscribed_returns_false_if_there_is_a_valid_key_but_expired() { - $account = factory(Account::class)->create(); - - $plan = factory(\Laravel\Cashier\Subscription::class)->create([ - 'account_id' => $account->id, - 'stripe_plan' => 'chandler_annual', - 'stripe_id' => 'sub_C0R444pbxddhW7', - 'name' => 'annualPlan', + Carbon::setTestNow(Carbon::create(2018, 1, 1)); + $account = factory(Account::class)->create([ + 'licence_key' => '123', + 'valid_until_at' => '1999-01-01', ]); - config(['monica.paid_plan_annual_friendly_name' => 'annualPlan']); - - $this->assertEquals( - true, - $account->isSubscribed() - ); - } - - /** @test */ - public function user_is_subscribed_returns_false_if_no_plan_is_set() - { - $account = factory(Account::class)->create(); - $this->assertEquals( false, $account->isSubscribed() diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php new file mode 100644 index 00000000000..810bf2b7b4a --- /dev/null +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -0,0 +1,92 @@ + '123']); + Http::fake(); + + $key = 'W3siZnJlcXVlbmN5IjoibW9udGhseSIsInB1cmNoYXNlcl9lbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsIm5leHRfY2hlY2tfYXQiOiIyMDIyLTA0LTAzVDAwOjAwOjAwLjAwMDAwMFoifV0='; + $account = factory(Account::class)->create([]); + + $request = [ + 'account_id' => $account->id, + 'licence_key' => $key, + ]; + + app(ActivateLicenceKey::class)->execute($request); + + $this->assertDatabaseHas('accounts', [ + 'id' => $account->id, + 'licence_key' => 'W3siZnJlcXVlbmN5IjoibW9udGhseSIsInB1cmNoYXNlcl9lbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsIm5leHRfY2hlY2tfYXQiOiIyMDIyLTA0LTAzVDAwOjAwOjAwLjAwMDAwMFoifV0=', + 'valid_until_at' => '2022-04-03 00:00:00', + 'purchaser_email' => 'admin@admin.com', + 'frequency' => 'monthly', + ]); + } + + /** @test */ + public function it_fails_if_wrong_parameters_are_given() + { + $request = []; + + $this->expectException(ValidationException::class); + app(ActivateLicenceKey::class)->execute($request); + } + + /** @test */ + public function it_fails_if_the_licence_key_does_not_exist() + { + $this->expectException(Exception::class); + + Http::fake(function ($request) { + return Http::response('', 404); + }); + + $account = factory(Account::class)->create([]); + + $request = [ + 'account_id' => $account->id, + 'licence_key' => '', + ]; + + app(ActivateLicenceKey::class)->execute($request); + } + + /** @test */ + public function it_fails_if_the_licence_key_is_not_valid_anymore() + { + $this->expectException(Exception::class); + + Http::fake(function ($request) { + return Http::response('', 900); + }); + + $key = 'W3siZnJlcXVlbmN5IjoibW9udGhseSIsInB1cmNoYXNlcl9lbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsIm5leHRfY2hlY2tfYXQiOiIyMDIyLTA0LTAzVDAwOjAwOjAwLjAwMDAwMFoifV0='; + $account = factory(Account::class)->create([]); + + $request = [ + 'account_id' => $account->id, + 'licence_key' => $key, + ]; + + app(ActivateLicenceKey::class)->execute($request); + } +} From 2cf35f6260f49e8e40d4014b1d8c6c7312fca504 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 9 Mar 2022 02:59:02 +0000 Subject: [PATCH 02/41] Apply fixes from StyleCI --- .../Settings/SubscriptionsController.php | 5 ++--- .../Account/Subscription/ActivateLicenceKey.php | 16 +++++++--------- ...03_08_115818_add_licence_keys_to_accounts.php | 4 ++-- tests/Unit/Models/AccountTest.php | 2 +- .../Subscription/ActivateLicenceKeyTest.php | 11 ++++------- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index b0de037ebd1..99914b7fc8e 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers\Settings; -use App\Exceptions\NoLicenceKeyEncryptionSetException; +use Exception; use Illuminate\View\View; use App\Traits\StripeCall; use App\Helpers\DateHelper; @@ -12,17 +12,16 @@ use App\Helpers\AccountHelper; use App\Helpers\InstanceHelper; use App\Exceptions\StripeException; -use Illuminate\Validation\ValidationException; use Illuminate\Support\Facades\App; use App\Http\Controllers\Controller; use Illuminate\Http\RedirectResponse; use Illuminate\Contracts\View\Factory; use Stripe\Exception\ApiErrorException; +use Illuminate\Validation\ValidationException; use Stripe\PaymentIntent as StripePaymentIntent; use Laravel\Cashier\Exceptions\IncompletePayment; use App\Services\Account\Settings\ArchiveAllContacts; use App\Services\Account\Subscription\ActivateLicenceKey; -use Exception; class SubscriptionsController extends Controller { diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 2032b6c599e..78b3b240806 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -2,17 +2,15 @@ namespace App\Services\Account\Subscription; -use App\Exceptions\NoCustomerPortalSetException; -use App\Exceptions\NoLicenceKeyEncryptionSetException; -use App\Models\Account\Account; -use App\Models\Account\Photo; -use App\Services\BaseService; use Exception; use Illuminate\Support\Str; +use App\Services\BaseService; +use App\Models\Account\Account; +use Illuminate\Support\Facades\App; use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Facades\App; +use App\Exceptions\NoCustomerPortalSetException; +use App\Exceptions\NoLicenceKeyEncryptionSetException; class ActivateLicenceKey extends BaseService { @@ -54,7 +52,7 @@ public function execute(array $data): void private function validateEnvVariables(): void { - if (!config('monica.licence_key_encryption_key')) { + if (! config('monica.licence_key_encryption_key')) { throw new NoLicenceKeyEncryptionSetException(); } @@ -65,7 +63,7 @@ private function validateEnvVariables(): void private function makeRequestToCustomerPortal(): void { - $url = config('monica.customer_portal_url') . '/validate/key/' . $this->data['licence_key']; + $url = config('monica.customer_portal_url').'/validate/key/'.$this->data['licence_key']; // necessary for testing purposes if (App::environment('production')) { diff --git a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php index 7a8ed1c586c..1b1661a1c4e 100644 --- a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php +++ b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php @@ -1,8 +1,8 @@ Date: Wed, 9 Mar 2022 07:50:45 -0500 Subject: [PATCH 03/41] wip --- .github/workflows/tests.yml | 2 +- app/Helpers/DateHelper.php | 17 - .../Settings/SubscriptionsController.php | 268 ---------- app/Providers/AppServiceProvider.php | 7 +- .../Subscription/ActivateLicenceKey.php | 2 +- composer.json | 1 - composer.lock | 501 ++---------------- config/app.php | 1 - config/cashier.php | 101 ---- config/monica.php | 11 + resources/lang/en/settings.php | 10 +- resources/sass/stripe.scss | 22 - resources/views/layouts/skeleton.blade.php | 22 +- .../views/partials/subscription.blade.php | 16 - .../settings/subscriptions/account.blade.php | 4 +- .../settings/subscriptions/archive.blade.php | 53 -- .../settings/subscriptions/confirm.blade.php | 36 -- .../downgrade-checklist.blade.php | 80 --- .../subscriptions/downgrade-success.blade.php | 70 --- .../settings/subscriptions/update.blade.php | 73 --- .../settings/subscriptions/upgrade.blade.php | 55 -- routes/web.php | 16 - tests/Unit/Helpers/DateHelperTest.php | 20 - webpack.mix.js | 4 - 24 files changed, 56 insertions(+), 1336 deletions(-) delete mode 100644 config/cashier.php delete mode 100644 resources/sass/stripe.scss delete mode 100644 resources/views/partials/subscription.blade.php delete mode 100644 resources/views/settings/subscriptions/archive.blade.php delete mode 100644 resources/views/settings/subscriptions/confirm.blade.php delete mode 100644 resources/views/settings/subscriptions/downgrade-checklist.blade.php delete mode 100644 resources/views/settings/subscriptions/downgrade-success.blade.php delete mode 100644 resources/views/settings/subscriptions/update.blade.php delete mode 100644 resources/views/settings/subscriptions/upgrade.blade.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 63d572220c0..98da5425037 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -79,7 +79,7 @@ jobs: mkdir -p public/js public/css results/coverage {\ echo "{"; \ - for f in app.js manifest.js vendor.js app-ltr.css app-rtl.css stripe.js stripe.css; do \ + for f in app.js manifest.js vendor.js app-ltr.css app-rtl.css; do \ [[ $first == 1 ]] && echo -n "," || first=1; \ k=${f##*.}/$f; \ echo "\"/$k\": \"/$k\""; \ diff --git a/app/Helpers/DateHelper.php b/app/Helpers/DateHelper.php index 8af4f8ac11a..b57d8b0b2e3 100644 --- a/app/Helpers/DateHelper.php +++ b/app/Helpers/DateHelper.php @@ -265,23 +265,6 @@ public static function getMonthAndYear(int $month): string return $date->translatedFormat($format) ?: ''; } - /** - * Gets the next theoritical billing date. - * This is used on the Upgrade page to tell the user when the next billing - * date would be if he subscribed. - * - * @param string $interval - * @return Carbon - */ - public static function getNextTheoriticalBillingDate(string $interval): Carbon - { - if ($interval == 'monthly') { - return now(static::getTimezone())->addMonth(); - } - - return now(static::getTimezone())->addYear(); - } - /** * Gets a list of all the year from min to max (0 is the current year). * diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index 99914b7fc8e..5c3449f1227 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -73,272 +73,4 @@ public function store(Request $request) return view('settings.subscriptions.success'); } - - /** - * Display the upgrade view page. - * - * @param Request $request - * @return View|Factory|RedirectResponse - */ - public function upgrade(Request $request) - { - if (! config('monica.requires_subscription')) { - return redirect()->route('settings.index'); - } - - if (auth()->user()->account->isSubscribed()) { - return redirect()->route('settings.subscriptions.index'); - } - - $plan = $request->query('plan'); - if ($plan !== 'monthly' && $plan !== 'annual') { - abort(404); - } - - $planInformation = InstanceHelper::getPlanInformationFromConfig($plan); - - if ($planInformation === null) { - abort(404); - } - - return view('settings.subscriptions.upgrade', [ - 'planInformation' => $planInformation, - 'nextTheoriticalBillingDate' => DateHelper::getFullDate(DateHelper::getNextTheoriticalBillingDate($plan)), - 'intent' => auth()->user()->account->createSetupIntent(), - ]); - } - - /** - * Display the update view page. - * - * @param Request $request - * @return View|Factory|RedirectResponse - */ - public function update(Request $request) - { - if (! config('monica.requires_subscription')) { - return redirect()->route('settings.index'); - } - - $account = auth()->user()->account; - - $subscription = $account->getSubscribedPlan(); - if (! $account->isSubscribed() && (! $subscription || $subscription->ended())) { - return view('settings.subscriptions.blank'); - } - - $planInformation = InstanceHelper::getPlanInformationFromSubscription($subscription); - - if ($planInformation === null) { - abort(404); - } - - $plans = collect(); - foreach (['monthly', 'annual'] as $plan) { - $plans->push(InstanceHelper::getPlanInformationFromConfig($plan)); - } - - $legacyPlan = null; - if (! $plans->contains(function ($value) use ($planInformation) { - return $value['id'] === $planInformation['id']; - })) { - $legacyPlan = $planInformation; - } - - return view('settings.subscriptions.update', [ - 'planInformation' => $planInformation, - 'plans' => $plans, - 'legacyPlan' => $legacyPlan, - ]); - } - - /** - * Process the update process. - * - * @param Request $request - * @return View|Factory|RedirectResponse - */ - public function processUpdate(Request $request) - { - $account = auth()->user()->account; - - $subscription = $account->getSubscribedPlan(); - if (! $account->isSubscribed() && ! $subscription) { - return redirect()->route('settings.index'); - } - - try { - $account->updateSubscription($request->input('frequency'), $subscription); - } catch (StripeException $e) { - return back() - ->withInput() - ->withErrors($e->getMessage()); - } - - return redirect()->route('settings.subscriptions.index'); - } - - /** - * Display the confirm view page. - * - * @return View|Factory|RedirectResponse - * - * @throws ApiErrorException - */ - public function confirmPayment($id) - { - try { - $payment = $this->stripeCall(function () use ($id) { - return StripePaymentIntent::retrieve($id, Cashier::stripeOptions()); - }); - } catch (StripeException $e) { - return back()->withErrors($e->getMessage()); - } - - return view('settings.subscriptions.confirm', [ - 'payment' => new Payment($payment), - 'redirect' => request('redirect'), - ]); - } - - /** - * Display the upgrade success page. - * - * @return View|Factory|RedirectResponse - */ - public function upgradeSuccess() - { - if (! config('monica.requires_subscription')) { - return redirect()->route('settings.index'); - } - - return view('settings.subscriptions.success'); - } - - /** - * Display the downgrade success page. - * - * @param Request $request - * @return View|Factory|RedirectResponse - */ - public function downgradeSuccess(Request $request) - { - if (! config('monica.requires_subscription')) { - return redirect()->route('settings.index'); - } - - return view('settings.subscriptions.downgrade-success'); - } - - /** - * Display the archive all your contacts page. - * - * @return View|Factory|RedirectResponse - */ - public function archive() - { - return view('settings.subscriptions.archive'); - } - - /** - * Process the Archive process. - * - * @return RedirectResponse - */ - public function processArchive() - { - app(ArchiveAllContacts::class)->execute([ - 'account_id' => auth()->user()->account_id, - ]); - - return redirect()->route('settings.subscriptions.downgrade'); - } - - /** - * Display the downgrade view page. - * - * @return View|Factory|RedirectResponse - */ - public function downgrade() - { - $account = auth()->user()->account; - - if (! config('monica.requires_subscription')) { - return redirect()->route('settings.index'); - } - - $subscription = $account->getSubscribedPlan(); - if (! $account->isSubscribed() && ! $subscription) { - return redirect()->route('settings.index'); - } - - return view('settings.subscriptions.downgrade-checklist') - ->with('numberOfActiveContacts', $account->allContacts()->active()->count()) - ->with('numberOfPendingInvitations', $account->invitations()->count()) - ->with('numberOfUsers', $account->users()->count()) - ->with('accountHasLimitations', AccountHelper::hasLimitations($account)) - ->with('hasReachedContactLimit', ! AccountHelper::isBelowContactLimit($account)) - ->with('canDowngrade', AccountHelper::canDowngrade($account)); - } - - /** - * Process the upgrade payment. - * - * @param Request $request - * @return RedirectResponse - */ - public function processPayment(Request $request) - { - if (! config('monica.requires_subscription')) { - return redirect()->route('settings.index'); - } - - try { - auth()->user()->account - ->subscribe($request->input('payment_method'), $request->input('plan')); - } catch (IncompletePayment $e) { - return redirect()->route( - 'settings.subscriptions.confirm', - [$e->payment->asStripePaymentIntent()->id, 'redirect' => route('settings.subscriptions.upgrade.success')] - ); - } catch (StripeException $e) { - return back() - ->withInput() - ->withErrors($e->getMessage()); - } - - return redirect()->route('settings.subscriptions.upgrade.success'); - } - - /** - * Download the invoice as PDF. - * - * @param mixed $invoiceId - * @return \Symfony\Component\HttpFoundation\Response - */ - public function downloadInvoice($invoiceId) - { - return auth()->user()->account->downloadInvoice($invoiceId, [ - 'vendor' => 'Monica', - 'product' => trans('settings.subscriptions_pdf_title', ['name' => config('monica.paid_plan_monthly_friendly_name')]), - ]); - } - - /** - * Download the invoice as PDF. - * - * @param Request $request - * @return \Illuminate\Http\RedirectResponse|null - */ - public function forceCompletePaymentOnTesting(Request $request): ?RedirectResponse - { - if (App::environment('production')) { - return null; - } - $subscription = auth()->user()->account->getSubscribedPlan(); - $subscription->stripe_status = 'active'; - $subscription->save(); - - return redirect()->route('settings.subscriptions.index'); - } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 6b513fe938f..14020381c47 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -126,12 +126,6 @@ public function boot() public function register() { Passport::ignoreMigrations(); - Cashier::ignoreMigrations(); - Cashier::formatCurrencyUsing(function ($amount, $currency) { - $currency = \App\Models\Settings\Currency::where('iso', strtoupper($currency ?? config('cashier.currency')))->first(); - - return \App\Helpers\MoneyHelper::format($amount, $currency); - }); } /** @@ -238,5 +232,6 @@ public function register() \App\Services\Instance\AuditLog\LogAccountAction::class => \App\Services\Instance\AuditLog\LogAccountAction::class, \App\Services\User\UpdateViewPreference::class => \App\Services\User\UpdateViewPreference::class, \App\Services\User\AcceptPolicy::class => \App\Services\User\AcceptPolicy::class, + \App\Services\Account\Subscription\ActivateLicenceKey::class => \App\Services\Account\Subscription\ActivateLicenceKey::class, ]; } diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 78b3b240806..ffbe9c9c59c 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -63,7 +63,7 @@ private function validateEnvVariables(): void private function makeRequestToCustomerPortal(): void { - $url = config('monica.customer_portal_url').'/validate/key/'.$this->data['licence_key']; + $url = config('monica.customer_portal_url').'/' . config('monica.customer_portal_secret_key') . '/validate/'.$this->data['licence_key']; // necessary for testing purposes if (App::environment('production')) { diff --git a/composer.json b/composer.json index 044aa87a2fe..d7d0467e1b0 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,6 @@ "giggsey/libphonenumber-for-php": "^8.9", "guzzlehttp/guzzle": "^7.2", "intervention/image": "^2.3", - "laravel/cashier": "^12.0", "laravel/framework": "^8.0", "laravel/passport": "^10.0", "laravel/socialite": "^5.0", diff --git a/composer.lock b/composer.lock index 27832cf646d..bdba3048f17 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": "dbb8a40531e1c39b654747f9c0d61cce", + "content-hash": "4f058cf63afafc4f544f177199cea565", "packages": [ { "name": "asbiin/laravel-adorable", @@ -219,16 +219,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.212.3", + "version": "3.212.4", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "1d3db6d276299136bcaa7896653be0dcd2aaa92a" + "reference": "4961e8b34fab8b92a459067f264b4dc66f969a57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1d3db6d276299136bcaa7896653be0dcd2aaa92a", - "reference": "1d3db6d276299136bcaa7896653be0dcd2aaa92a", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/4961e8b34fab8b92a459067f264b4dc66f969a57", + "reference": "4961e8b34fab8b92a459067f264b4dc66f969a57", "shasum": "" }, "require": { @@ -304,9 +304,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.212.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.212.4" }, - "time": "2022-03-07T19:48:01+00:00" + "time": "2022-03-08T19:19:48+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1487,73 +1487,6 @@ ], "time": "2022-02-28T11:07:21+00:00" }, - { - "name": "dompdf/dompdf", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/dompdf/dompdf.git", - "reference": "60b704331479a69e9bcdb3496da2315b5c4f94fd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/60b704331479a69e9bcdb3496da2315b5c4f94fd", - "reference": "60b704331479a69e9bcdb3496da2315b5c4f94fd", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "phenx/php-font-lib": "^0.5.4", - "phenx/php-svg-lib": "^0.3.3 || ^0.4.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "mockery/mockery": "^1.3", - "phpunit/phpunit": "^7.5 || ^8 || ^9", - "squizlabs/php_codesniffer": "^3.5" - }, - "suggest": { - "ext-gd": "Needed to process images", - "ext-gmagick": "Improves image processing performance", - "ext-imagick": "Improves image processing performance", - "ext-zlib": "Needed for pdf stream compression" - }, - "type": "library", - "autoload": { - "psr-4": { - "Dompdf\\": "src/" - }, - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - }, - { - "name": "Brian Sweeney", - "email": "eclecticgeek@gmail.com" - }, - { - "name": "Gabriel Bull", - "email": "me@gabrielbull.com" - } - ], - "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", - "homepage": "https://github.com/dompdf/dompdf", - "support": { - "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v1.2.0" - }, - "time": "2022-02-07T13:02:10+00:00" - }, { "name": "dragonmantank/cron-expression", "version": "v3.3.1", @@ -2972,97 +2905,18 @@ }, "time": "2021-10-08T21:21:46+00:00" }, - { - "name": "laravel/cashier", - "version": "v12.17.0", - "source": { - "type": "git", - "url": "https://github.com/laravel/cashier-stripe.git", - "reference": "da1a55e9b3e711669bdf7055b0af42cfd762af0e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/cashier-stripe/zipball/da1a55e9b3e711669bdf7055b0af42cfd762af0e", - "reference": "da1a55e9b3e711669bdf7055b0af42cfd762af0e", - "shasum": "" - }, - "require": { - "dompdf/dompdf": "^0.8.6|^1.0.1", - "ext-json": "*", - "illuminate/console": "^6.0|^7.0|^8.0|^9.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0", - "illuminate/database": "^6.0|^7.0|^8.0|^9.0", - "illuminate/http": "^6.0|^7.0|^8.0|^9.0", - "illuminate/log": "^6.0|^7.0|^8.0|^9.0", - "illuminate/notifications": "^6.0|^7.0|^8.0|^9.0", - "illuminate/routing": "^6.0|^7.0|^8.0|^9.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0", - "illuminate/view": "^6.0|^7.0|^8.0|^9.0", - "moneyphp/money": "^3.2", - "nesbot/carbon": "^2.0", - "php": "^7.2.5|^8.0", - "stripe/stripe-php": "^7.39", - "symfony/http-kernel": "^4.3|^5.0|^6.0", - "symfony/polyfill-intl-icu": "^1.22.1" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0", - "phpunit/phpunit": "^8.0|^9.0" - }, - "suggest": { - "ext-intl": "Allows for more locales besides the default \"en\" when formatting money values." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "12.x-dev" - }, - "laravel": { - "providers": [ - "Laravel\\Cashier\\CashierServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Cashier\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.", - "keywords": [ - "billing", - "laravel", - "stripe" - ], - "support": { - "issues": "https://github.com/laravel/cashier/issues", - "source": "https://github.com/laravel/cashier" - }, - "time": "2022-01-25T19:18:52+00:00" - }, { "name": "laravel/framework", - "version": "v8.83.3", + "version": "v8.83.4", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "b4ed222a188cca74ca9062296e525d26ae54a0ce" + "reference": "97a549f1a83cfb32dab1eecab4c4d40a984a72b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/b4ed222a188cca74ca9062296e525d26ae54a0ce", - "reference": "b4ed222a188cca74ca9062296e525d26ae54a0ce", + "url": "https://api.github.com/repos/laravel/framework/zipball/97a549f1a83cfb32dab1eecab4c4d40a984a72b5", + "reference": "97a549f1a83cfb32dab1eecab4c4d40a984a72b5", "shasum": "" }, "require": { @@ -3222,34 +3076,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-03-03T15:14:29+00:00" + "time": "2022-03-08T16:12:54+00:00" }, { "name": "laravel/passport", - "version": "v10.3.2", + "version": "v10.3.3", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "c56207e9a37c849da0164842a609a9f38747e95b" + "reference": "1039d8b4aa71c45dbea2f140b131cae8802237e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/c56207e9a37c849da0164842a609a9f38747e95b", - "reference": "c56207e9a37c849da0164842a609a9f38747e95b", + "url": "https://api.github.com/repos/laravel/passport/zipball/1039d8b4aa71c45dbea2f140b131cae8802237e7", + "reference": "1039d8b4aa71c45dbea2f140b131cae8802237e7", "shasum": "" }, "require": { "ext-json": "*", "firebase/php-jwt": "^5.0", - "illuminate/auth": "^8.2|^9.0", - "illuminate/console": "^8.2|^9.0", - "illuminate/container": "^8.2|^9.0", - "illuminate/contracts": "^8.2|^9.0", - "illuminate/cookie": "^8.2|^9.0", - "illuminate/database": "^8.2|^9.0", - "illuminate/encryption": "^8.2|^9.0", - "illuminate/http": "^8.2|^9.0", - "illuminate/support": "^8.2|^9.0", + "illuminate/auth": "^8.37|^9.0", + "illuminate/console": "^8.37|^9.0", + "illuminate/container": "^8.37|^9.0", + "illuminate/contracts": "^8.37|^9.0", + "illuminate/cookie": "^8.37|^9.0", + "illuminate/database": "^8.37|^9.0", + "illuminate/encryption": "^8.37|^9.0", + "illuminate/http": "^8.37|^9.0", + "illuminate/support": "^8.37|^9.0", "lcobucci/jwt": "^3.4|^4.0", "league/oauth2-server": "^8.2", "nyholm/psr7": "^1.3", @@ -3299,7 +3153,7 @@ "issues": "https://github.com/laravel/passport/issues", "source": "https://github.com/laravel/passport" }, - "time": "2022-02-15T21:44:15+00:00" + "time": "2022-02-23T15:04:04+00:00" }, { "name": "laravel/serializable-closure", @@ -5921,96 +5775,6 @@ }, "time": "2022-02-21T01:04:05+00:00" }, - { - "name": "phenx/php-font-lib", - "version": "0.5.4", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", - "shasum": "" - }, - "require": { - "ext-mbstring": "*" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5" - }, - "type": "library", - "autoload": { - "psr-4": { - "FontLib\\": "src/FontLib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - } - ], - "description": "A library to read, parse, export and make subsets of different types of font files.", - "homepage": "https://github.com/PhenX/php-font-lib", - "support": { - "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" - }, - "time": "2021-12-17T19:44:54+00:00" - }, - { - "name": "phenx/php-svg-lib", - "version": "0.4.1", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "4498b5df7b08e8469f0f8279651ea5de9626ed02" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/4498b5df7b08e8469f0f8279651ea5de9626ed02", - "reference": "4498b5df7b08e8469f0f8279651ea5de9626ed02", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^7.2 || ^7.3 || ^7.4 || ^8.0", - "sabberworm/php-css-parser": "^8.4" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Svg\\": "src/Svg" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - } - ], - "description": "A library to read, parse and export to PDF SVG files.", - "homepage": "https://github.com/PhenX/php-svg-lib", - "support": { - "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.4.1" - }, - "time": "2022-03-07T12:52:04+00:00" - }, { "name": "php-http/client-common", "version": "2.5.0", @@ -7959,59 +7723,6 @@ ], "time": "2021-09-25T23:10:38+00:00" }, - { - "name": "sabberworm/php-css-parser", - "version": "8.4.0", - "source": { - "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=5.6.20" - }, - "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" - }, - "suggest": { - "ext-mbstring": "for parsing UTF-8 CSS" - }, - "type": "library", - "autoload": { - "psr-4": { - "Sabberworm\\CSS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Raphael Schweikert" - } - ], - "description": "Parser for CSS Files written in PHP", - "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", - "keywords": [ - "css", - "parser", - "stylesheet" - ], - "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" - }, - "time": "2021-12-11T13:40:54+00:00" - }, { "name": "sabre/dav", "version": "4.3.1", @@ -8971,66 +8682,6 @@ }, "time": "2022-02-16T13:52:28+00:00" }, - { - "name": "stripe/stripe-php", - "version": "v7.116.0", - "source": { - "type": "git", - "url": "https://github.com/stripe/stripe-php.git", - "reference": "7a39f594f213ed3f443a95adf769d1ecbc8393e7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stripe/stripe-php/zipball/7a39f594f213ed3f443a95adf769d1ecbc8393e7", - "reference": "7a39f594f213ed3f443a95adf769d1ecbc8393e7", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "php": ">=5.6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "3.5.0", - "phpstan/phpstan": "^1.2", - "phpunit/phpunit": "^5.7 || ^9.0", - "squizlabs/php_codesniffer": "^3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "Stripe\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Stripe and contributors", - "homepage": "https://github.com/stripe/stripe-php/contributors" - } - ], - "description": "Stripe PHP Library", - "homepage": "https://stripe.com/", - "keywords": [ - "api", - "payment processing", - "stripe" - ], - "support": { - "issues": "https://github.com/stripe/stripe-php/issues", - "source": "https://github.com/stripe/stripe-php/tree/v7.116.0" - }, - "time": "2022-03-02T15:51:15+00:00" - }, { "name": "swiftmailer/swiftmailer", "version": "v6.3.0", @@ -10377,93 +10028,6 @@ ], "time": "2021-11-23T21:10:46+00:00" }, - { - "name": "symfony/polyfill-intl-icu", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "c023a439b8551e320cc3c8433b198e408a623af1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/c023a439b8551e320cc3c8433b198e408a623af1", - "reference": "c023a439b8551e320cc3c8433b198e408a623af1", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance and support of other locales than \"en\"" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Icu\\": "" - }, - "classmap": [ - "Resources/stubs" - ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's ICU-related data and classes", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "icu", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.25.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-10-26T17:16:04+00:00" - }, { "name": "symfony/polyfill-intl-idn", "version": "v1.25.0", @@ -16778,12 +16342,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "6c48c3048166dc4142a1a5f28a325faed3a578a3" + "reference": "9461fa5df0b505bbe4404f20b1759884a27c7572" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/6c48c3048166dc4142a1a5f28a325faed3a578a3", - "reference": "6c48c3048166dc4142a1a5f28a325faed3a578a3", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9461fa5df0b505bbe4404f20b1759884a27c7572", + "reference": "9461fa5df0b505bbe4404f20b1759884a27c7572", "shasum": "" }, "conflict": { @@ -16867,7 +16431,7 @@ "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<=1.5.25", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<=1.3.1", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.12", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", "ezsystems/ezplatform-user": ">=1,<1.0.1", @@ -16955,6 +16519,7 @@ "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", "marcwillmann/turn": "<0.3.3", + "matyhtf/framework": "<=3.0.5", "mautic/core": "<4.2|= 2.13.1", "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", "microweber/microweber": "<1.3", @@ -17034,7 +16599,7 @@ "remdex/livehelperchat": "<3.93", "rmccue/requests": ">=1.6,<1.8", "robrichards/xmlseclibs": "<3.0.4", - "rudloff/alltube": "<3.0.2", + "rudloff/alltube": "<3.0.3", "s-cart/s-cart": "<6.7.2", "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", @@ -17226,7 +16791,7 @@ "type": "tidelift" } ], - "time": "2022-03-05T18:49:45+00:00" + "time": "2022-03-09T12:04:57+00:00" }, { "name": "sebastian/cli-parser", diff --git a/config/app.php b/config/app.php index fcde27d7bc8..ee5f50cc990 100644 --- a/config/app.php +++ b/config/app.php @@ -210,7 +210,6 @@ App\Providers\RouteServiceProvider::class, Laravel\Socialite\SocialiteServiceProvider::class, Intervention\Image\ImageServiceProvider::class, - Laravel\Cashier\CashierServiceProvider::class, Laravel\Passport\PassportServiceProvider::class, Creativeorange\Gravatar\GravatarServiceProvider::class, App\Providers\DAVServiceProvider::class, diff --git a/config/cashier.php b/config/cashier.php deleted file mode 100644 index 1e336a27f76..00000000000 --- a/config/cashier.php +++ /dev/null @@ -1,101 +0,0 @@ - env('STRIPE_KEY'), - - 'secret' => env('STRIPE_SECRET'), - - /* - |-------------------------------------------------------------------------- - | Cashier Path - |-------------------------------------------------------------------------- - | - | This is the base URI path where Cashier's views, such as the payment - | verification screen, will be available from. You're free to tweak - | this path according to your preferences and application design. - | - */ - - 'path' => env('CASHIER_PATH', 'stripe'), - - /* - |-------------------------------------------------------------------------- - | Stripe Webhooks - |-------------------------------------------------------------------------- - | - | Your Stripe webhook secret is used to prevent unauthorized requests to - | your Stripe webhook handling controllers. The tolerance setting will - | check the drift between the current time and the signed request's. - | - */ - - 'webhook' => [ - 'secret' => env('STRIPE_WEBHOOK_SECRET'), - 'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300), - ], - - /* - |-------------------------------------------------------------------------- - | Cashier Model - |-------------------------------------------------------------------------- - | - | This is the model in your application that implements the Billable trait - | provided by Cashier. It will serve as the primary model you use while - | interacting with Cashier related methods, subscriptions, and so on. - | - */ - - 'model' => env('CASHIER_MODEL', App\Models\Account\Account::class), - - /* - |-------------------------------------------------------------------------- - | Currency - |-------------------------------------------------------------------------- - | - | This is the default currency that will be used when generating charges - | from your application. Of course, you are welcome to use any of the - | various world currencies that are currently supported via Stripe. - | - */ - - 'currency' => env('CASHIER_CURRENCY', 'usd'), - - /* - |-------------------------------------------------------------------------- - | Currency Locale - |-------------------------------------------------------------------------- - | - | This is the default locale in which your money values are formatted in - | for display. To utilize other locales besides the default en locale - | verify you have the "intl" PHP extension installed on the system. - | - */ - - 'currency_locale' => env('CASHIER_CURRENCY_LOCALE', 'en'), - - /* - |-------------------------------------------------------------------------- - | Payment Confirmation Notification - |-------------------------------------------------------------------------- - | - | If this setting is enabled, Cashier will automatically notify customers - | whose payments require additional verification. You should listen to - | Stripe's webhooks in order for this feature to function correctly. - | - */ - - 'payment_notification' => env('CASHIER_PAYMENT_NOTIFICATION'), - -]; diff --git a/config/monica.php b/config/monica.php index c1b755fcc8d..259dcfe8bbb 100644 --- a/config/monica.php +++ b/config/monica.php @@ -306,4 +306,15 @@ | */ 'licence_key_encryption_key' => env('LICENCE_KEY_ENCRYPTION_KEY', null), + + /* + |-------------------------------------------------------------------------- + | Secret key to communicate with the customer portal + |-------------------------------------------------------------------------- + | + | We need to communicate with the customer portal to check licence keys. + | This is done through an HTTP call that we need to secure. + | + */ + 'customer_portal_secret_key' => env('CUSTOMER_PORTAL_SECRET_KEY', null), ]; diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 4a262818f73..bb555197f72 100644 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -239,15 +239,6 @@ 'subscriptions_downgrade_success' => 'You are back to the Free plan!', 'subscriptions_downgrade_thanks' => 'Thanks so much for trying the paid plan. We keep adding new features on Monica all the time – so you might want to come back in the future to see if you might be interested in taking a subscription again.', 'subscriptions_back' => 'Back to settings', - 'subscriptions_upgrade_title' => 'Upgrade your account', - 'subscriptions_upgrade_choose' => 'You picked the :plan plan.', - 'subscriptions_upgrade_infos' => 'We couldn’t be happier. Enter your payment info below.', - 'subscriptions_upgrade_name' => 'Name on card', - 'subscriptions_upgrade_zip' => 'ZIP or postal code', - 'subscriptions_upgrade_credit' => 'Credit or debit card', - 'subscriptions_upgrade_submit' => 'Pay {amount}', - 'subscriptions_upgrade_charge' => 'We’ll charge your card :price now. The next charge will be on :date. If you ever change your mind, you can cancel at any time, no questions asked.', - 'subscriptions_upgrade_charge_handled' => 'The payment is handled by Stripe. No card information touches our server.', 'subscriptions_upgrade_success' => 'Thank you! You are now subscribed.', 'subscriptions_upgrade_thanks' => 'Welcome to the community of people who try to make the world a better place.', @@ -287,6 +278,7 @@ 'subscriptions_licence_key_problem' => 'There is a problem with the system.', 'subscriptions_licence_key_frequency_monthly' => 'Monthly', 'subscriptions_licence_key_frequency_annual' => 'Annual', + 'subscriptions_account_invoices' => 'Your invoices are available on the customer portal.', 'stripe_error_card' => 'Your card was declined. Decline message is: :message', 'stripe_error_api_connection' => 'Network communication with Stripe failed. Try again later.', diff --git a/resources/sass/stripe.scss b/resources/sass/stripe.scss deleted file mode 100644 index 73c2a547e4c..00000000000 --- a/resources/sass/stripe.scss +++ /dev/null @@ -1,22 +0,0 @@ -.StripeElement { - background-color: #ffffff; - height: 45px; - width: 100%; - padding: 13px 12px; - border-radius: 4px; - border: 1px solid #999999; - -webkit-transition: box-shadow 150ms ease; - transition: box-shadow 150ms ease; -} - -.StripeElement--focus { - box-shadow: 0 1px 3px 0 #d0d0d0; -} - -.StripeElement--invalid { - border-color: #d9534f; -} - -.StripeElement--webkit-autofill { - background-color: #fffacd !important; -} diff --git a/resources/views/layouts/skeleton.blade.php b/resources/views/layouts/skeleton.blade.php index 028015e3865..e18fe567270 100644 --- a/resources/views/layouts/skeleton.blade.php +++ b/resources/views/layouts/skeleton.blade.php @@ -15,10 +15,6 @@ - {{-- Required only for the Upgrade account page --}} - @if (Route::currentRouteName() == 'settings.subscriptions.upgrade' || Route::currentRouteName() == 'settings.subscriptions.confirm') - - @endif @@ -42,16 +38,11 @@
    - @if (Route::currentRouteName() != 'settings.subscriptions.confirm') - @include('partials.header') - @include('partials.subscription') - @endif + @include('partials.header') @yield('content')
    - @if (Route::currentRouteName() != 'settings.subscriptions.confirm') - @include('partials.footer') - @endif + @include('partials.footer') {{-- THE JS FILE OF THE APP --}} @push('scripts') @@ -59,12 +50,9 @@ @endpush - {{-- Load everywhere except on the Upgrade account page --}} - @if (Route::currentRouteName() != 'settings.subscriptions.upgrade' && Route::currentRouteName() != 'settings.subscriptions.confirm') - @push('scripts') - - @endpush - @endif + @push('scripts') + + @endpush @stack('scripts') diff --git a/resources/views/partials/subscription.blade.php b/resources/views/partials/subscription.blade.php deleted file mode 100644 index e30097ac04b..00000000000 --- a/resources/views/partials/subscription.blade.php +++ /dev/null @@ -1,16 +0,0 @@ -@if (($subscription = auth()->user()->account->getSubscribedPlan()) && $subscription->hasIncompletePayment()) - -
    - {!! trans('settings.subscriptions_account_confirm_payment', ['url' => route('settings.subscriptions.confirm', $subscription->latestPayment() ? $subscription->latestPayment()->id : '')]) !!} -
    - -@if (! app()->environment('production')) -

    - - {{-- No translation needed --}} - Force payment success (test). - -

    -@endif - -@endif diff --git a/resources/views/settings/subscriptions/account.blade.php b/resources/views/settings/subscriptions/account.blade.php index f61e7bf95f9..41ccb5662ce 100644 --- a/resources/views/settings/subscriptions/account.blade.php +++ b/resources/views/settings/subscriptions/account.blade.php @@ -35,10 +35,12 @@
    -

    {{ trans('settings.subscriptions_account_current_plan') }}

    +

    {{ trans('settings.subscriptions_account_current_plan') }}

    {{ trans('settings.subscriptions_account_current_paid_plan', ['name' => $planInformation]) }}

    +

    {!! trans('settings.subscriptions_account_invoices', ['url' => $customerPortalUrl]) !!}

    +
    diff --git a/resources/views/settings/subscriptions/archive.blade.php b/resources/views/settings/subscriptions/archive.blade.php deleted file mode 100644 index 2f664bbac43..00000000000 --- a/resources/views/settings/subscriptions/archive.blade.php +++ /dev/null @@ -1,53 +0,0 @@ -@extends('layouts.skeleton') - -@section('content') - -
    - - {{-- Breadcrumb --}} - - -
    -
    -
    -
    - @include('partials.errors') - -
    -
    -

    {{ trans('settings.archive_title') }}

    - -

    {{ trans('settings.archive_desc') }}

    - -
    - @csrf - -

    - -
    - -
    -
    -
    -
    -
    - - @endsection diff --git a/resources/views/settings/subscriptions/confirm.blade.php b/resources/views/settings/subscriptions/confirm.blade.php deleted file mode 100644 index 4e2b2b61ca9..00000000000 --- a/resources/views/settings/subscriptions/confirm.blade.php +++ /dev/null @@ -1,36 +0,0 @@ -@extends('layouts.skeleton') - -@section('content') - -
    - -
    -
    - @if (! $payment->isSucceeded() && ! $payment->isCancelled()) -

    {{ trans('settings.subscriptions_payment_confirm_title', ['amount' => $payment->amount()]) }}

    -

    {{ trans('settings.subscriptions_payment_confirm_information') }}

    - @endif - - @include('partials.errors') - - -
    -
    -
    - -@endsection - -@push('scripts') - - -@endpush diff --git a/resources/views/settings/subscriptions/downgrade-checklist.blade.php b/resources/views/settings/subscriptions/downgrade-checklist.blade.php deleted file mode 100644 index 2e828aaaed2..00000000000 --- a/resources/views/settings/subscriptions/downgrade-checklist.blade.php +++ /dev/null @@ -1,80 +0,0 @@ -@extends('layouts.skeleton') - -@section('content') - -
    - - {{-- Breadcrumb --}} - - -
    -
    -
    -
    - @include('partials.errors') - -

    {{ trans('settings.subscriptions_downgrade_title') }}

    - -

    {{ trans('settings.subscriptions_downgrade_limitations') }}

    - -
      - -
    • - - {{ trans('settings.subscriptions_downgrade_rule_users') }} - {!! trans_choice('settings.subscriptions_downgrade_rule_users_constraint', $numberOfUsers, ['url' => route('settings.users.index'), 'count' => $numberOfUsers]) !!} -
    • - -
    • - - {{ trans('settings.subscriptions_downgrade_rule_invitations') }} - {!! trans_choice('settings.subscriptions_downgrade_rule_invitations_constraint', $numberOfPendingInvitations, ['url' => route('settings.users.index'), 'count' => $numberOfPendingInvitations]) !!} -
    • - -
    • - - {{ trans('settings.subscriptions_downgrade_rule_contacts', ['number' => config('monica.number_of_allowed_contacts_free_account')]) }} - {!! trans_choice('settings.subscriptions_downgrade_rule_contacts_constraint', $numberOfActiveContacts, ['url' => '/people', 'count' => $numberOfActiveContacts]) !!} - @if ($hasReachedContactLimit) - {!! trans('settings.subscriptions_downgrade_rule_contacts_archive', ['url' => route('settings.subscriptions.archive')]) !!} - @endif -
    • - -
    - -
    - @csrf - - @if ($canDowngrade) -

    - @else -

    - @endif - -
    - -
    -
    -
    -
    -
    - -@endsection diff --git a/resources/views/settings/subscriptions/downgrade-success.blade.php b/resources/views/settings/subscriptions/downgrade-success.blade.php deleted file mode 100644 index 06781b9d1d7..00000000000 --- a/resources/views/settings/subscriptions/downgrade-success.blade.php +++ /dev/null @@ -1,70 +0,0 @@ -@extends('layouts.skeleton') - -@section('content') - -
    - - {{-- Breadcrumb --}} - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -

    {{ trans('settings.subscriptions_downgrade_success') }}

    -

    {{ trans('settings.subscriptions_downgrade_thanks') }}

    -

    {{trans('settings.subscriptions_back') }}

    -
    -
    -
    - -@endsection diff --git a/resources/views/settings/subscriptions/update.blade.php b/resources/views/settings/subscriptions/update.blade.php deleted file mode 100644 index 594cd6dec2a..00000000000 --- a/resources/views/settings/subscriptions/update.blade.php +++ /dev/null @@ -1,73 +0,0 @@ -@extends('layouts.skeleton') - -@section('content') - -
    - - {{-- Breadcrumb --}} - - -
    -
    -
    -
    - -

    {{ trans('settings.subscriptions_account_update_title') }}

    - -

    {{ trans('settings.subscriptions_account_update_description') }}

    - - @if ($legacyPlan) -
    - - -
    - @endif - -
    - @csrf - - @foreach ($plans as $plan) -
    - - -
    - @endforeach - -

    {{ trans('settings.subscriptions_account_update_information') }}

    - -
    - - {{ trans('app.cancel') }} -
    -
    - -
    -
    -
    -
    -
    - -@endsection diff --git a/resources/views/settings/subscriptions/upgrade.blade.php b/resources/views/settings/subscriptions/upgrade.blade.php deleted file mode 100644 index 7d75752e3bf..00000000000 --- a/resources/views/settings/subscriptions/upgrade.blade.php +++ /dev/null @@ -1,55 +0,0 @@ -@extends('layouts.skeleton') - -@section('content') - -
    - - {{-- Breadcrumb --}} - - -
    -
    -

    {{ trans('settings.subscriptions_upgrade_choose', ['plan' => $planInformation['type']]) }}

    -

    {{ trans('settings.subscriptions_upgrade_infos') }}

    - - @include('partials.errors') - - -

    {{ trans('settings.subscriptions_upgrade_charge', ['price' => $planInformation['friendlyPrice'], 'date' => $nextTheoriticalBillingDate]) }}

    -

    {!! trans('settings.subscriptions_upgrade_charge_handled', ['url' => 'https://stripe.com']) !!}

    -
    -
    -
    - -@endsection - -@push('scripts') - - -@endpush diff --git a/routes/web.php b/routes/web.php index 50c6e1c40e8..9c4612cfd93 100644 --- a/routes/web.php +++ b/routes/web.php @@ -273,22 +273,6 @@ Route::name('subscriptions.')->group(function () { Route::get('/settings/subscriptions', 'Settings\\SubscriptionsController@index')->name('index'); Route::post('/settings/subscriptions', 'Settings\\SubscriptionsController@store')->name('store'); - - Route::get('/settings/subscriptions/upgrade', 'Settings\\SubscriptionsController@upgrade')->name('upgrade'); - Route::get('/settings/subscriptions/upgrade/success', 'Settings\\SubscriptionsController@upgradeSuccess')->name('upgrade.success'); - Route::get('/settings/subscriptions/update', 'Settings\\SubscriptionsController@update')->name('update'); - Route::post('/settings/subscriptions/update', 'Settings\\SubscriptionsController@processUpdate'); - Route::get('/settings/subscriptions/confirmPayment/{id}', 'Settings\\SubscriptionsController@confirmPayment')->name('confirm'); - Route::post('/settings/subscriptions/processPayment', 'Settings\\SubscriptionsController@processPayment')->name('payment'); - Route::get('/settings/subscriptions/invoice/{invoice}', 'Settings\\SubscriptionsController@downloadInvoice')->name('invoice'); - Route::get('/settings/subscriptions/downgrade', 'Settings\\SubscriptionsController@downgrade')->name('downgrade'); - Route::post('/settings/subscriptions/downgrade', 'Settings\\SubscriptionsController@processDowngrade'); - Route::get('/settings/subscriptions/archive', 'Settings\\SubscriptionsController@archive')->name('archive'); - Route::post('/settings/subscriptions/archive', 'Settings\\SubscriptionsController@processArchive'); - Route::get('/settings/subscriptions/downgrade/success', 'Settings\\SubscriptionsController@downgradeSuccess')->name('downgrade.success'); - if (! App::environment('production')) { - Route::get('/settings/subscriptions/forceCompletePaymentOnTesting', 'Settings\\SubscriptionsController@forceCompletePaymentOnTesting')->name('forceCompletePaymentOnTesting'); - } }); Route::get('/settings/auditlogs', 'Settings\\AuditLogController@index')->name('auditlog.index'); diff --git a/tests/Unit/Helpers/DateHelperTest.php b/tests/Unit/Helpers/DateHelperTest.php index 9a4e0c7d360..297bb4e304a 100644 --- a/tests/Unit/Helpers/DateHelperTest.php +++ b/tests/Unit/Helpers/DateHelperTest.php @@ -450,26 +450,6 @@ public function test_get_month_and_year() ); } - public function test_it_gets_date_one_month_from_now() - { - Carbon::setTestNow(Carbon::create(2017, 1, 1)); - - $this->assertEquals( - '2017-02-01', - DateHelper::getNextTheoriticalBillingDate('monthly')->toDateString() - ); - } - - public function test_it_gets_date_one_year_from_now() - { - Carbon::setTestNow(Carbon::create(2017, 1, 1)); - - $this->assertEquals( - '2018-01-01', - DateHelper::getNextTheoriticalBillingDate('yearly')->toDateString() - ); - } - public function test_it_returns_a_list_with_years() { $user = $this->signIn(); diff --git a/webpack.mix.js b/webpack.mix.js index 990acb0315a..c1c35a5de08 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -44,10 +44,6 @@ mix.js('resources/js/app.js', 'public/js').vue() .sass('resources/sass/app-ltr.scss', 'public/css') .sass('resources/sass/app-rtl.scss', 'public/css') - // stripe - .js('resources/js/stripe.js', 'public/js') - .sass('resources/sass/stripe.scss', 'public/css') - .alias({ vue$: path.join(__dirname, 'node_modules/vue/dist/vue.esm.js'), }) From 1956aa1b1641f698d4c936461669b6429c552797 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 9 Mar 2022 12:51:00 +0000 Subject: [PATCH 04/41] Apply fixes from StyleCI --- .../Controllers/Settings/SubscriptionsController.php | 9 --------- app/Providers/AppServiceProvider.php | 1 - app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- routes/web.php | 1 - 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index 5c3449f1227..552cdc84220 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -7,20 +7,11 @@ use App\Traits\StripeCall; use App\Helpers\DateHelper; use Illuminate\Http\Request; -use Laravel\Cashier\Cashier; -use Laravel\Cashier\Payment; use App\Helpers\AccountHelper; -use App\Helpers\InstanceHelper; -use App\Exceptions\StripeException; -use Illuminate\Support\Facades\App; use App\Http\Controllers\Controller; use Illuminate\Http\RedirectResponse; use Illuminate\Contracts\View\Factory; -use Stripe\Exception\ApiErrorException; use Illuminate\Validation\ValidationException; -use Stripe\PaymentIntent as StripePaymentIntent; -use Laravel\Cashier\Exceptions\IncompletePayment; -use App\Services\Account\Settings\ArchiveAllContacts; use App\Services\Account\Subscription\ActivateLicenceKey; class SubscriptionsController extends Controller diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 14020381c47..9236cdf1aaa 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,7 +3,6 @@ namespace App\Providers; use App\Helpers\DBHelper; -use Laravel\Cashier\Cashier; use Laravel\Passport\Passport; use Illuminate\Console\Command; use Illuminate\Support\Facades\App; diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index ffbe9c9c59c..2be2bf1b080 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -63,7 +63,7 @@ private function validateEnvVariables(): void private function makeRequestToCustomerPortal(): void { - $url = config('monica.customer_portal_url').'/' . config('monica.customer_portal_secret_key') . '/validate/'.$this->data['licence_key']; + $url = config('monica.customer_portal_url').'/'.config('monica.customer_portal_secret_key').'/validate/'.$this->data['licence_key']; // necessary for testing purposes if (App::environment('production')) { diff --git a/routes/web.php b/routes/web.php index 9c4612cfd93..5ac4958d552 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,5 @@ Date: Wed, 9 Mar 2022 08:03:36 -0500 Subject: [PATCH 05/41] wip --- app/Helpers/InstanceHelper.php | 40 --- .../Settings/SubscriptionsController.php | 3 - .../Account/Settings/DestroyAccount.php | 17 - app/Traits/StripeCall.php | 55 ---- app/Traits/Subscription.php | 125 -------- database/factories/SettingsFactory.php | 11 - .../js/components/settings/Subscription.vue | 297 ------------------ resources/lang/en/settings.php | 45 +-- tests/Feature/AccountSubscriptionTest.php | 94 ------ tests/Unit/Helpers/InstanceHelperTest.php | 56 ---- tests/Unit/Models/AccountTest.php | 73 ----- 11 files changed, 1 insertion(+), 815 deletions(-) delete mode 100644 app/Traits/StripeCall.php delete mode 100644 resources/js/components/settings/Subscription.vue diff --git a/app/Helpers/InstanceHelper.php b/app/Helpers/InstanceHelper.php index 5d4a9adf3f7..d7df3ce0f80 100644 --- a/app/Helpers/InstanceHelper.php +++ b/app/Helpers/InstanceHelper.php @@ -38,46 +38,6 @@ public static function getPlanInformationFromConfig(string $timePeriod): ?array ]; } - /** - * Get the plan information for the given time period. - * - * @param \Laravel\Cashier\Subscription $subscription - * @return array|null - */ - public static function getPlanInformationFromSubscription(\Laravel\Cashier\Subscription $subscription): ?array - { - try { - $stripeSubscription = $subscription->asStripeSubscription(); - $plan = $stripeSubscription->plan; - } catch (\Stripe\Exception\ApiErrorException $e) { - $stripeSubscription = null; - $plan = null; - } - - if (is_null($stripeSubscription) || is_null($plan)) { - return [ - 'type' => $subscription->stripe_plan, - 'name' => $subscription->name, - 'id' => $subscription->stripe_id, - 'price' => '?', - 'friendlyPrice' => '?', - 'nextBillingDate' => '', - ]; - } - - $currency = Currency::where('iso', strtoupper($plan->currency))->first(); - $amount = MoneyHelper::format($plan->amount, $currency); - - return [ - 'type' => $plan->interval === 'month' ? 'monthly' : 'annual', - 'name' => $subscription->name, - 'id' => $plan->id, - 'price' => $plan->amount, - 'friendlyPrice' => $amount, - 'nextBillingDate' => DateHelper::getFullDate(Carbon::createFromTimestamp($stripeSubscription->current_period_end)), - ]; - } - /** * Get changelogs entries. * diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index 552cdc84220..347d46cca78 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -4,7 +4,6 @@ use Exception; use Illuminate\View\View; -use App\Traits\StripeCall; use App\Helpers\DateHelper; use Illuminate\Http\Request; use App\Helpers\AccountHelper; @@ -16,8 +15,6 @@ class SubscriptionsController extends Controller { - use StripeCall; - /** * Display a listing of the resource. * diff --git a/app/Services/Account/Settings/DestroyAccount.php b/app/Services/Account/Settings/DestroyAccount.php index 4627b580cd8..90fd1458ac1 100644 --- a/app/Services/Account/Settings/DestroyAccount.php +++ b/app/Services/Account/Settings/DestroyAccount.php @@ -38,8 +38,6 @@ public function execute(array $data): void $this->destroyPhotos($account); - $this->cancelStripe($account); - $account->delete(); } @@ -68,19 +66,4 @@ private function destroyPhotos(Account $account) 'account_id' => $account->id, ]); } - - /** - * Cancel Stripe subscription. - * - * @param Account $account - * @return void - * - * @throws StripeException - */ - private function cancelStripe(Account $account) - { - if ($account->isSubscribed() && ! $account->has_access_to_paid_version_for_free) { - $account->subscriptionCancel(); - } - } } diff --git a/app/Traits/StripeCall.php b/app/Traits/StripeCall.php deleted file mode 100644 index a36bc117224..00000000000 --- a/app/Traits/StripeCall.php +++ /dev/null @@ -1,55 +0,0 @@ -getJsonBody(); - $err = $body['error']; - $errorMessage = trans('settings.stripe_error_card', ['message' => $err['message']]); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe card decline error: '.$e->getMessage(), ['body' => $e->getJsonBody(), $e]); - } catch (\Stripe\Exception\RateLimitException $e) { - // Too many requests made to the API too quickly - $errorMessage = trans('settings.stripe_error_rate_limit'); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe RateLimit error: '.$e->getMessage(), ['body' => $e->getJsonBody(), $e]); - } catch (\Stripe\Exception\InvalidRequestException $e) { - // Invalid parameters were supplied to Stripe's API - $errorMessage = trans('settings.stripe_error_invalid_request'); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe InvalidRequest error: '.$e->getMessage(), ['body' => $e->getJsonBody(), $e]); - } catch (\Stripe\Exception\AuthenticationException $e) { - // Authentication with Stripe's API failed - // (maybe you changed API keys recently) - $errorMessage = trans('settings.stripe_error_authentication'); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe Authentication error: '.$e->getMessage(), ['body' => $e->getJsonBody(), $e]); - } catch (\Stripe\Exception\ApiConnectionException $e) { - // Network communication with Stripe failed - $errorMessage = trans('settings.stripe_error_api_connection_error'); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe ApiConnection error: '.$e->getMessage(), ['body' => $e->getJsonBody(), $e]); - } catch (\Stripe\Exception\ApiErrorException $e) { - $errorMessage = $e->getMessage(); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe error: '.$e->getMessage(), ['body' => $e->getJsonBody(), $e]); - } catch (\Laravel\Cashier\Exceptions\IncompletePayment $e) { - throw $e; - } catch (\Exception $e) { - $errorMessage = $e->getMessage(); - Log::error(__CLASS__.' '.__FUNCTION__.': Stripe error: '.$e->getMessage(), [$e]); - } - - throw new StripeException($errorMessage); - } -} diff --git a/app/Traits/Subscription.php b/app/Traits/Subscription.php index e891de34952..26443d33329 100644 --- a/app/Traits/Subscription.php +++ b/app/Traits/Subscription.php @@ -2,69 +2,8 @@ namespace App\Traits; -use Laravel\Cashier\Billable; -use App\Helpers\InstanceHelper; - trait Subscription { - use Billable, StripeCall; - - /** - * Process the upgrade payment. - * - * @param string $payment_method - * @param string $planName - * @return bool|string - */ - public function subscribe(string $payment_method, string $planName) - { - $plan = InstanceHelper::getPlanInformationFromConfig($planName); - if ($plan === null) { - abort(404); - } - - return $this->stripeCall(function () use ($payment_method, $plan) { - $this->newSubscription($plan['name'], $plan['id']) - ->create($payment_method, [ - 'email' => auth()->user()->email, - ]); - - return true; - }); - } - - /** - * Update an existing subscription. - * - * @param string $planName - * @param \Laravel\Cashier\Subscription $subscription - * @return \Laravel\Cashier\Subscription - */ - public function updateSubscription(string $planName, \Laravel\Cashier\Subscription $subscription) - { - $oldPlan = $subscription->stripe_plan; - $plan = InstanceHelper::getPlanInformationFromConfig($planName); - if ($plan === null) { - abort(404); - } - - if ($oldPlan === $planName) { - // No change - return $subscription; - } - - $subscription = $this->stripeCall(function () use ($subscription, $plan) { - return $subscription->swap($plan['id']); - }); - - if ($subscription->stripe_plan !== $oldPlan && $subscription->stripe_plan === $plan['id']) { - $subscription->forceFill([ - 'name' => $plan['name'], - ])->save(); - } - - return $subscription; - } /** * Check if the account is currently subscribed to a plan. @@ -87,68 +26,4 @@ public function isSubscribed() return true; } - - /** - * Get the subscription the account is subscribed to. - * - * @return \Laravel\Cashier\Subscription|null - */ - public function getSubscribedPlan() - { - return $this->subscriptions()->recurring()->first(); - } - - /** - * Get the id of the plan the account is subscribed to. - * - * @return string - */ - public function getSubscribedPlanId() - { - $plan = $this->getSubscribedPlan(); - - return is_null($plan) ? '' : $plan->stripe_plan; - } - - /** - * Get the friendly name of the plan the account is subscribed to. - * - * @return string|null - */ - public function getSubscribedPlanName(): ?string - { - $plan = $this->getSubscribedPlan(); - - return is_null($plan) ? null : $plan->name; - } - - /** - * Cancel the plan the account is subscribed to. - * - * @return bool|string - */ - public function subscriptionCancel() - { - $plan = $this->getSubscribedPlan(); - - if (! is_null($plan)) { - return $this->stripeCall(function () use ($plan) { - $plan->cancelNow(); - - return true; - }); - } - - return false; - } - - /** - * Check if the account has invoices linked to this account. - * - * @return bool - */ - public function hasInvoices() - { - return $this->subscriptions()->count() > 0; - } } diff --git a/database/factories/SettingsFactory.php b/database/factories/SettingsFactory.php index e27721e07a7..5351b287312 100644 --- a/database/factories/SettingsFactory.php +++ b/database/factories/SettingsFactory.php @@ -16,14 +16,3 @@ 'symbol' => $faker->realText(10), ]; }); - -$factory->define(\Laravel\Cashier\Subscription::class, function (Faker\Generator $faker) { - return [ - 'account_id' => factory(App\Models\Account\Account::class)->create()->id, - 'name' => $faker->word(), - 'stripe_id' => $faker->word(), - 'stripe_plan' => $faker->randomElement(['plan-1', 'plan-2', 'plan-3']), - 'quantity' => 1, - 'created_at' => now(), - ]; -}); diff --git a/resources/js/components/settings/Subscription.vue b/resources/js/components/settings/Subscription.vue deleted file mode 100644 index e2a06f11781..00000000000 --- a/resources/js/components/settings/Subscription.vue +++ /dev/null @@ -1,297 +0,0 @@ - - - diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index bb555197f72..acbd8855952 100644 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -202,56 +202,19 @@ 'subscriptions_account_next_billing_title' => 'Next bill', 'subscriptions_account_next_billing' => 'Your subscription will auto-renew on :date.', - 'subscriptions_account_bill_monthly' => 'We’ll bill you :price for another month.', 'subscriptions_account_bill_annual' => 'We’ll bill you :price for another year.', 'subscriptions_account_change' => 'Change plan', + 'subscriptions_account_payment' => 'Which payment option fits you best?', 'subscriptions_account_cancel_title' => 'Cancel subscription', 'subscriptions_account_cancel_action' => 'Cancel subscription', 'subscriptions_account_cancel' => 'You can cancel your subscription at any time.', - 'subscriptions_account_free_plan' => 'You are on the free plan.', - 'subscriptions_account_free_plan_upgrade' => 'You can upgrade your account to the :name plan, which costs $:price per month. Here are the advantages:', - 'subscriptions_account_free_plan_benefits_users' => 'Unlimited number of users', - 'subscriptions_account_free_plan_benefits_reminders' => 'Reminders by email', - 'subscriptions_account_free_plan_benefits_import_data_vcard' => 'Import your contacts with vCard', - 'subscriptions_account_free_plan_benefits_support' => 'Support the project in the long run, so we can introduce more great features.', - 'subscriptions_account_upgrade' => 'Upgrade your account', 'subscriptions_account_upgrade_title' => 'Upgrade Monica today and have more meaningful relationships.', 'subscriptions_account_upgrade_choice' => 'Monica requires a licence key to be completely functional.', - 'subscriptions_account_update_title' => 'Update Monica subscription', - 'subscriptions_account_update_description' => 'You can change your subscription’s frequency here.', - 'subscriptions_account_update_information' => 'You will be billed immediately for the new amount. Your subscription will extend to the new period, depending on your choice.', - 'subscriptions_account_invoices' => 'Invoices', - 'subscriptions_account_invoices_download' => 'Download', - 'subscriptions_account_invoices_subscription' => 'Subscription from :startDate to :endDate', - 'subscriptions_account_payment' => 'Which payment option fits you best?', - 'subscriptions_account_confirm_payment' => 'Your payment is currently incomplete, please confirm your payment.', - 'subscriptions_downgrade_title' => 'Downgrade your account to the free plan', - 'subscriptions_downgrade_limitations' => 'The free plan has limitations. In order to be able to downgrade, you need to pass the checklist below:', - 'subscriptions_downgrade_rule_users' => 'You must have only 1 user in your account', - 'subscriptions_downgrade_rule_users_constraint' => 'You currently have 1 user in your account.|You currently have :count users in your account.', - 'subscriptions_downgrade_rule_invitations' => 'You must not have any pending invitations', - 'subscriptions_downgrade_rule_invitations_constraint' => 'You currently have 1 pending invitation.|You currently have :count pending invitations.', - 'subscriptions_downgrade_rule_contacts' => 'You must not have more than :number active contacts', - 'subscriptions_downgrade_rule_contacts_constraint' => 'You currently have 1 contact.|You currently have :count contacts.', - 'subscriptions_downgrade_rule_contacts_archive' => 'We can also archive all your contacts for you – that would clear this rule and let you proceed with your account’s downgrade process.', - 'subscriptions_downgrade_cta' => 'Downgrade', - 'subscriptions_downgrade_success' => 'You are back to the Free plan!', - 'subscriptions_downgrade_thanks' => 'Thanks so much for trying the paid plan. We keep adding new features on Monica all the time – so you might want to come back in the future to see if you might be interested in taking a subscription again.', 'subscriptions_back' => 'Back to settings', 'subscriptions_upgrade_success' => 'Thank you! You are now subscribed.', 'subscriptions_upgrade_thanks' => 'Welcome to the community of people who try to make the world a better place.', - 'subscriptions_payment_confirm_title' => 'Confirm your :amount payment', - 'subscriptions_payment_confirm_information' => 'Extra confirmation is needed to process your payment. Please confirm your payment by filling out your payment details below.', - 'subscriptions_payment_succeeded_title' => 'Payment Successful', - 'subscriptions_payment_succeeded' => 'This payment was already successfully confirmed.', - 'subscriptions_payment_cancelled_title' => 'Payment Cancelled', - 'subscriptions_payment_cancelled' => 'This payment was cancelled.', - 'subscriptions_payment_error_name' => 'Please provide your name.', - 'subscriptions_payment_success' => 'The payment was successful.', - - 'subscriptions_pdf_title' => 'Your :name monthly subscription', 'subscriptions_plan_frequency_year' => ':amount / year', 'subscriptions_plan_frequency_month' => ':amount / month', 'subscriptions_plan_choose' => 'Get your licence key', @@ -280,12 +243,6 @@ 'subscriptions_licence_key_frequency_annual' => 'Annual', 'subscriptions_account_invoices' => 'Your invoices are available on the customer portal.', - 'stripe_error_card' => 'Your card was declined. Decline message is: :message', - 'stripe_error_api_connection' => 'Network communication with Stripe failed. Try again later.', - 'stripe_error_rate_limit' => 'Too many requests with Stripe right now. Try again later.', - 'stripe_error_invalid_request' => 'Invalid parameters. Try again later.', - 'stripe_error_authentication' => 'Wrong authentication with Stripe', - 'import_title' => 'Import contacts in your account', 'import_cta' => 'Upload contacts', 'import_stat' => 'You’ve imported :number files so far.', diff --git a/tests/Feature/AccountSubscriptionTest.php b/tests/Feature/AccountSubscriptionTest.php index 155524fd718..26657933d03 100644 --- a/tests/Feature/AccountSubscriptionTest.php +++ b/tests/Feature/AccountSubscriptionTest.php @@ -122,16 +122,6 @@ protected static function deleteStripeResource($resource) } } - public function test_it_throw_an_error_on_subscribe() - { - $user = $this->signin(); - $user->email = 'test_it_throw_an_error_on_subscribe@monica-test.com'; - $user->save(); - - $this->expectException(\App\Exceptions\StripeException::class); - $user->account->subscribe('xxx', 'annual'); - } - public function test_it_sees_the_plan_names() { $user = $this->signin(); @@ -141,21 +131,6 @@ public function test_it_sees_the_plan_names() $response->assertSee('Pick a plan below and join over 0 persons who upgraded their Monica.'); } - public function test_it_get_the_plan_name() - { - $user = $this->signin(); - - factory(Subscription::class)->create([ - 'account_id' => $user->account_id, - 'name' => 'Annual', - 'stripe_plan' => 'annual', - 'stripe_id' => 'test', - 'quantity' => 1, - ]); - - $this->assertEquals('Annual', $user->account->getSubscribedPlanName()); - } - public function test_it_get_subscription_page() { $user = $this->signin(); @@ -173,75 +148,6 @@ public function test_it_get_subscription_page() $response->assertSee('You are on the Annual plan. Thanks so much for being a subscriber.'); } - public function test_it_get_upgrade_page() - { - $user = $this->signin(); - - $response = $this->get('/settings/subscriptions/upgrade?plan=annual'); - - $response->assertSee('You picked the annual plan.'); - } - - public function test_it_subscribe() - { - $user = $this->signin(); - $user->email = 'test_it_subscribe@monica-test.com'; - $user->save(); - - $response = $this->post('/settings/subscriptions/processPayment', [ - 'payment_method' => 'pm_card_visa', - 'plan' => 'annual', - ]); - - $response->assertRedirect('/settings/subscriptions/upgrade/success'); - } - - public function test_it_subscribe_with_2nd_auth() - { - $user = $this->signin(); - $user->email = 'test_it_subscribe_with_2nd_auth@monica-test.com'; - $user->save(); - - $response = $this->followingRedirects()->post('/settings/subscriptions/processPayment', [ - 'payment_method' => 'pm_card_threeDSecure2Required', - 'plan' => 'annual', - ]); - - $response->assertSee('Extra confirmation is needed to process your payment.'); - } - - public function test_it_subscribe_with_error() - { - $user = $this->signin(); - $user->email = 'test_it_subscribe_with_error@monica-test.com'; - $user->save(); - - $response = $this->post('/settings/subscriptions/processPayment', [ - 'payment_method' => 'error', - 'plan' => 'annual', - ], [ - 'HTTP_REFERER' => 'back', - ]); - - $response->assertRedirect('/back'); - } - - public function test_it_does_not_subscribe() - { - $user = $this->signin(); - $user->email = 'test_it_does_not_subscribe@monica-test.com'; - $user->save(); - - try { - $user->account->subscribe('pm_card_chargeDeclined', 'annual'); - } catch (\App\Exceptions\StripeException $e) { - $this->assertEquals('Your card was declined. Decline message is: Your card was declined.', $e->getMessage()); - - return; - } - $this->fail(); - } - public function test_it_get_blank_page_on_update_if_not_subscribed() { $this->signin(); diff --git a/tests/Unit/Helpers/InstanceHelperTest.php b/tests/Unit/Helpers/InstanceHelperTest.php index a908596da64..d39214a1211 100644 --- a/tests/Unit/Helpers/InstanceHelperTest.php +++ b/tests/Unit/Helpers/InstanceHelperTest.php @@ -80,62 +80,6 @@ public function it_fetches_the_annually_plan_information() ); } - /** @test */ - public function it_fetches_subscription_information() - { - $stripeSubscription = (object) [ - 'plan' => (object) [ - 'currency' => 'USD', - 'amount' => 500, - 'interval' => 'month', - 'id' => 'monthly', - ], - 'current_period_end' => 1629976560, - ]; - - $subscription = Mockery::mock('\Laravel\Cashier\Subscription'); - $subscription->shouldReceive('asStripeSubscription') - ->andReturn($stripeSubscription); - $subscription->shouldReceive('getAttribute') - ->with('name') - ->andReturn('Monthly'); - - $this->assertEquals( - 'monthly', - InstanceHelper::getPlanInformationFromSubscription($subscription)['type'] - ); - - $this->assertEquals( - 'Monthly', - InstanceHelper::getPlanInformationFromSubscription($subscription)['name'] - ); - - $this->assertEquals( - 'monthly', - InstanceHelper::getPlanInformationFromSubscription($subscription)['id'] - ); - - $this->assertEquals( - 500, - InstanceHelper::getPlanInformationFromSubscription($subscription)['price'] - ); - - $this->assertEquals( - '$5.00', - InstanceHelper::getPlanInformationFromSubscription($subscription)['friendlyPrice'] - ); - } - - /** @test */ - public function it_returns_null_when_fetching_an_unknown_plan_information() - { - $account = new Account; - - $this->assertNull( - InstanceHelper::getPlanInformationFromConfig('unknown_plan') - ); - } - /** @test */ public function it_gets_latest_changelog_entries() { diff --git a/tests/Unit/Models/AccountTest.php b/tests/Unit/Models/AccountTest.php index 466f3a89c3a..3aa21d459f5 100644 --- a/tests/Unit/Models/AccountTest.php +++ b/tests/Unit/Models/AccountTest.php @@ -317,79 +317,6 @@ public function user_is_subscribed_returns_false_if_there_is_a_valid_key_but_exp ); } - /** @test */ - public function has_invoices_returns_true_if_a_plan_exists() - { - $account = factory(Account::class)->create(); - - $plan = factory(\Laravel\Cashier\Subscription::class)->create([ - 'account_id' => $account->id, - 'stripe_plan' => 'chandler_5', - 'stripe_id' => 'sub_C0R444pbxddhW7', - 'name' => 'fakePlan', - ]); - - $this->assertTrue($account->hasInvoices()); - } - - /** @test */ - public function has_invoices_returns_false_if_a_plan_does_not_exist() - { - $account = factory(Account::class)->create(); - - $this->assertFalse($account->hasInvoices()); - } - - /** @test */ - public function it_gets_the_id_of_the_subscribed_plan() - { - config([ - 'monica.paid_plan_annual_friendly_name' => 'fakePlan', - 'monica.paid_plan_annual_id' => 'chandler_5', - ]); - - $user = $this->signIn(); - - $account = $user->account; - - $plan = factory(\Laravel\Cashier\Subscription::class)->create([ - 'account_id' => $account->id, - 'stripe_plan' => 'chandler_5', - 'stripe_id' => 'sub_C0R444pbxddhW7', - 'name' => 'fakePlan', - ]); - - $this->assertEquals( - 'chandler_5', - $account->getSubscribedPlanId() - ); - } - - /** @test */ - public function it_gets_the_friendly_name_of_the_subscribed_plan() - { - config([ - 'monica.paid_plan_annual_friendly_name' => 'fakePlan', - 'monica.paid_plan_annual_id' => 'chandler_5', - ]); - - $user = $this->signIn(); - - $account = $user->account; - - $plan = factory(\Laravel\Cashier\Subscription::class)->create([ - 'account_id' => $account->id, - 'stripe_plan' => 'chandler_5', - 'stripe_id' => 'sub_C0R444pbxddhW7', - 'name' => 'fakePlan', - ]); - - $this->assertEquals( - 'fakePlan', - $account->getSubscribedPlanName() - ); - } - /** @test */ public function it_populates_the_account_with_three_default_genders() { From 736acae3bb9beb23e60c89bd4dc7e14fc871d09b Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 9 Mar 2022 13:03:48 +0000 Subject: [PATCH 06/41] Apply fixes from StyleCI --- app/Helpers/InstanceHelper.php | 1 - app/Traits/Subscription.php | 1 - tests/Unit/Helpers/InstanceHelperTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/app/Helpers/InstanceHelper.php b/app/Helpers/InstanceHelper.php index d7df3ce0f80..33b452ccac6 100644 --- a/app/Helpers/InstanceHelper.php +++ b/app/Helpers/InstanceHelper.php @@ -2,7 +2,6 @@ namespace App\Helpers; -use Carbon\Carbon; use function Safe\json_decode; use App\Models\Account\Account; use App\Models\Instance\Instance; diff --git a/app/Traits/Subscription.php b/app/Traits/Subscription.php index 26443d33329..f2a202bc0d0 100644 --- a/app/Traits/Subscription.php +++ b/app/Traits/Subscription.php @@ -4,7 +4,6 @@ trait Subscription { - /** * Check if the account is currently subscribed to a plan. * diff --git a/tests/Unit/Helpers/InstanceHelperTest.php b/tests/Unit/Helpers/InstanceHelperTest.php index d39214a1211..f280df85c66 100644 --- a/tests/Unit/Helpers/InstanceHelperTest.php +++ b/tests/Unit/Helpers/InstanceHelperTest.php @@ -2,7 +2,6 @@ namespace Tests\Unit\Helpers; -use Mockery; use Tests\TestCase; use function Safe\json_decode; use App\Helpers\InstanceHelper; From af214e89c1e9f83839435f8637dabc5e97392fa7 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Wed, 9 Mar 2022 11:55:05 -0500 Subject: [PATCH 07/41] wip --- app/Console/Kernel.php | 3 ++ app/Helpers/InstanceHelper.php | 2 - app/Jobs/Settings/CheckLicenceKeys.php | 46 +++++++++++++++++++ .../Subscription/ValidateLicenceKey.php | 46 ------------------- 4 files changed, 49 insertions(+), 48 deletions(-) create mode 100644 app/Jobs/Settings/CheckLicenceKeys.php delete mode 100644 app/Services/Account/Subscription/ValidateLicenceKey.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 0a13d4ab226..a38694523de 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -3,6 +3,7 @@ namespace App\Console; use App\Console\Scheduling\CronEvent; +use App\Jobs\Settings\CheckLicenceKeys; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -54,6 +55,8 @@ protected function schedule(Schedule $schedule) $this->scheduleCommand($schedule, 'cloudflare:reload', 'daily'); } $this->scheduleCommand($schedule, 'model:prune', 'daily'); + + $schedule->job(new CheckLicenceKeys)->everySixHours(); } /** diff --git a/app/Helpers/InstanceHelper.php b/app/Helpers/InstanceHelper.php index 33b452ccac6..fc2ccca3f94 100644 --- a/app/Helpers/InstanceHelper.php +++ b/app/Helpers/InstanceHelper.php @@ -3,8 +3,6 @@ namespace App\Helpers; use function Safe\json_decode; -use App\Models\Account\Account; -use App\Models\Instance\Instance; use App\Models\Settings\Currency; use Illuminate\Support\Facades\DB; use function Safe\file_get_contents; diff --git a/app/Jobs/Settings/CheckLicenceKeys.php b/app/Jobs/Settings/CheckLicenceKeys.php new file mode 100644 index 00000000000..1911acd9146 --- /dev/null +++ b/app/Jobs/Settings/CheckLicenceKeys.php @@ -0,0 +1,46 @@ +whereNotNull('licence_key') + ->get(); + + foreach ($accounts as $account) { + app(ActivateLicenceKey::class)->execute([ + 'account_id' => $account->id, + 'licence_key' => $account->licence_key, + ]); + } + } +} diff --git a/app/Services/Account/Subscription/ValidateLicenceKey.php b/app/Services/Account/Subscription/ValidateLicenceKey.php deleted file mode 100644 index a6eee2584b0..00000000000 --- a/app/Services/Account/Subscription/ValidateLicenceKey.php +++ /dev/null @@ -1,46 +0,0 @@ - 'required|integer|exists:accounts,id', - 'licence_key' => 'required|integer|exists:photos,id', - ]; - } - - /** - * Destroy a photo. - * - * @param array $data - * @return bool - */ - public function execute(array $data): bool - { - $this->validate($data); - - $photo = Photo::where('account_id', $data['account_id']) - ->findOrFail($data['photo_id']); - - // Delete the physical photo - // Throws FileNotFoundException - Storage::delete($photo->new_filename); - - // Delete the object in the DB - $photo->delete(); - - return true; - } -} From b316fac8bc525271c7e27576af32015ff2a1931d Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 9 Mar 2022 16:55:19 +0000 Subject: [PATCH 08/41] Apply fixes from StyleCI --- app/Jobs/Settings/CheckLicenceKeys.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/Jobs/Settings/CheckLicenceKeys.php b/app/Jobs/Settings/CheckLicenceKeys.php index 1911acd9146..167d4718f20 100644 --- a/app/Jobs/Settings/CheckLicenceKeys.php +++ b/app/Jobs/Settings/CheckLicenceKeys.php @@ -2,16 +2,14 @@ namespace App\Jobs\Settings; -use App\Models\Account\Account; +use Carbon\Carbon; use Illuminate\Bus\Queueable; -use App\Models\Contact\Contact; -use App\Services\Account\Subscription\ActivateLicenceKey; +use App\Models\Account\Account; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; -use App\Services\Contact\Avatar\GetAvatarsFromInternet as GetAvatarsFromInternetService; -use Carbon\Carbon; +use App\Services\Account\Subscription\ActivateLicenceKey; class CheckLicenceKeys implements ShouldQueue { From 0af387cf34df3e52a584af3be2735995bd58b0f6 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Thu, 10 Mar 2022 20:29:01 -0500 Subject: [PATCH 09/41] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a2b813d408..42c3097bcfc 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "composer update": "COMPOSER_MEMORY_LIMIT=-1 composer update" }, "engines": { - "node": "17.x", + "node": "16.x", "yarn": "1.22.x" }, "devDependencies": { From 0ddd47bae6e1bf936f6e00ba8b84b2c2c1f26d26 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Thu, 10 Mar 2022 20:31:04 -0500 Subject: [PATCH 10/41] Update composer.lock --- composer.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/composer.lock b/composer.lock index 90c1b152fca..f118d5c8a29 100644 --- a/composer.lock +++ b/composer.lock @@ -219,16 +219,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.212.5", + "version": "3.212.6", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "ed69594b385233bb895342e18008cd811e8225e7" + "reference": "fcb57b1f840938813e83f521e169914a076b3be9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ed69594b385233bb895342e18008cd811e8225e7", - "reference": "ed69594b385233bb895342e18008cd811e8225e7", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fcb57b1f840938813e83f521e169914a076b3be9", + "reference": "fcb57b1f840938813e83f521e169914a076b3be9", "shasum": "" }, "require": { @@ -304,9 +304,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.212.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.212.6" }, - "time": "2022-03-09T19:19:58+00:00" + "time": "2022-03-10T19:14:38+00:00" }, { "name": "bacon/bacon-qr-code", @@ -2054,16 +2054,16 @@ }, { "name": "giggsey/libphonenumber-for-php", - "version": "8.12.44", + "version": "8.12.45", "source": { "type": "git", "url": "https://github.com/giggsey/libphonenumber-for-php.git", - "reference": "a726990faf05bfffdd826f75d9b41a1580dad4a7" + "reference": "7f494fd3b87c7d83472e8b6126eedc6b72dd3f3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/a726990faf05bfffdd826f75d9b41a1580dad4a7", - "reference": "a726990faf05bfffdd826f75d9b41a1580dad4a7", + "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/7f494fd3b87c7d83472e8b6126eedc6b72dd3f3e", + "reference": "7f494fd3b87c7d83472e8b6126eedc6b72dd3f3e", "shasum": "" }, "require": { @@ -2123,7 +2123,7 @@ "issues": "https://github.com/giggsey/libphonenumber-for-php/issues", "source": "https://github.com/giggsey/libphonenumber-for-php" }, - "time": "2022-02-24T09:38:54+00:00" + "time": "2022-03-10T10:28:34+00:00" }, { "name": "giggsey/locale", @@ -16342,12 +16342,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "9461fa5df0b505bbe4404f20b1759884a27c7572" + "reference": "57a3432393ef9539465dc9c36d8cf5b045fe0800" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9461fa5df0b505bbe4404f20b1759884a27c7572", - "reference": "9461fa5df0b505bbe4404f20b1759884a27c7572", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/57a3432393ef9539465dc9c36d8cf5b045fe0800", + "reference": "57a3432393ef9539465dc9c36d8cf5b045fe0800", "shasum": "" }, "conflict": { @@ -16617,7 +16617,7 @@ "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", "silverstripe/framework": "<4.10.1", - "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", "silverstripe/subsites": ">=2,<2.1.1", @@ -16791,7 +16791,7 @@ "type": "tidelift" } ], - "time": "2022-03-09T12:04:57+00:00" + "time": "2022-03-10T00:11:32+00:00" }, { "name": "sebastian/cli-parser", From 2e93998bc82ded5588cc1de7f571e8fd61124b16 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sat, 14 May 2022 16:15:54 -0400 Subject: [PATCH 11/41] Update app/Services/Account/Subscription/ActivateLicenceKey.php Co-authored-by: Alexis Saettler --- app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 2be2bf1b080..9df83c9595d 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -75,7 +75,7 @@ private function makeRequestToCustomerPortal(): void private function checkResponseCode(): void { - if ($this->response->status() == 404) { + if ($this->response->status() === 404) { throw new Exception(trans('settings.subscriptions_licence_key_does_not_exist')); } From 8778755b2a9102dfacf7a969b80550b309bc368d Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 14 May 2022 20:16:14 +0000 Subject: [PATCH 12/41] Apply fixes from StyleCI --- tests/Unit/Services/VCard/ImportVCardTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Services/VCard/ImportVCardTest.php b/tests/Unit/Services/VCard/ImportVCardTest.php index a166c8158d8..0df1717b765 100644 --- a/tests/Unit/Services/VCard/ImportVCardTest.php +++ b/tests/Unit/Services/VCard/ImportVCardTest.php @@ -1377,6 +1377,6 @@ public function it_imports_uuid_contact() 'id' => $contact->id, 'uuid' => '31fdc242-c974-436e-98de-6b21624d6e34', ]); - $this->assertEquals('31fdc242-c974-436e-98de-6b21624d6e34', $contact->uuid, ); + $this->assertEquals('31fdc242-c974-436e-98de-6b21624d6e34', $contact->uuid); } } From 6e43528621c7395f47e14ef51738e2b4504b9ff4 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:17:54 -0400 Subject: [PATCH 13/41] Update resources/views/settings/subscriptions/blank.blade.php Co-authored-by: Alexis Saettler --- resources/views/settings/subscriptions/blank.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/settings/subscriptions/blank.blade.php b/resources/views/settings/subscriptions/blank.blade.php index 318854ee7eb..e634a79bfdc 100644 --- a/resources/views/settings/subscriptions/blank.blade.php +++ b/resources/views/settings/subscriptions/blank.blade.php @@ -68,7 +68,7 @@

    {{ trans('settings.subscriptions_plan_month_title') }}

    - {{ trans('settings.subscriptions_plan_choose') }} + {{ trans('settings.subscriptions_plan_choose') }}

    {{ trans('settings.subscriptions_plan_frequency_month', ['amount' => \App\Helpers\InstanceHelper::getPlanInformationFromConfig('monthly')['friendlyPrice']]) }} From 0289cfe4813df8def1e42dd8fdf9878ec3cebd18 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:18:07 -0400 Subject: [PATCH 14/41] Update resources/views/settings/subscriptions/blank.blade.php Co-authored-by: Alexis Saettler --- resources/views/settings/subscriptions/blank.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/settings/subscriptions/blank.blade.php b/resources/views/settings/subscriptions/blank.blade.php index e634a79bfdc..f022646c9ca 100644 --- a/resources/views/settings/subscriptions/blank.blade.php +++ b/resources/views/settings/subscriptions/blank.blade.php @@ -43,7 +43,7 @@

    {{ trans('settings.subscriptions_plan_year_title') }}

    - {{ trans('settings.subscriptions_plan_choose') }} + {{ trans('settings.subscriptions_plan_choose') }}

    {{ trans('settings.subscriptions_plan_frequency_year', ['amount' => \App\Helpers\InstanceHelper::getPlanInformationFromConfig('annual')['friendlyPrice']]) }} From 5163375ceaf07458468dd102e982b9c2e74afe3e Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:18:50 -0400 Subject: [PATCH 15/41] Update app/Services/Account/Subscription/ActivateLicenceKey.php Co-authored-by: Alexis Saettler --- app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 9df83c9595d..98b793d35d2 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -79,7 +79,7 @@ private function checkResponseCode(): void throw new Exception(trans('settings.subscriptions_licence_key_does_not_exist')); } - if ($this->response->status() == 900) { + if ($this->response->status() === 900) { throw new Exception(trans('settings.subscriptions_licence_key_invalid')); } From d05d621b84571c5cf1672b82a5113730a1ec3651 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:19:01 -0400 Subject: [PATCH 16/41] Update app/Services/Account/Subscription/ActivateLicenceKey.php Co-authored-by: Alexis Saettler --- app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 98b793d35d2..5738f30cf9f 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -83,7 +83,7 @@ private function checkResponseCode(): void throw new Exception(trans('settings.subscriptions_licence_key_invalid')); } - if ($this->response->status() != 200) { + if ($this->response->status() !== 200) { throw new Exception(trans('settings.subscriptions_licence_key_problem')); } } From fecc952b17972527cb2a38a2f37756400bc18872 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:22:53 -0400 Subject: [PATCH 17/41] Update app/Services/Account/Subscription/ActivateLicenceKey.php Co-authored-by: Alexis Saettler --- app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 5738f30cf9f..08180179060 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -56,7 +56,7 @@ private function validateEnvVariables(): void throw new NoLicenceKeyEncryptionSetException(); } - if (config('monica.customer_portal_url') == '') { + if (config('monica.customer_portal_url') === '') { throw new NoCustomerPortalSetException(); } } From 444113e5fa3f2e64d3b0bedb268d9f79091e6fc8 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:23:01 -0400 Subject: [PATCH 18/41] Update app/Jobs/Settings/CheckLicenceKeys.php Co-authored-by: Alexis Saettler --- app/Jobs/Settings/CheckLicenceKeys.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/Settings/CheckLicenceKeys.php b/app/Jobs/Settings/CheckLicenceKeys.php index 167d4718f20..174b914b345 100644 --- a/app/Jobs/Settings/CheckLicenceKeys.php +++ b/app/Jobs/Settings/CheckLicenceKeys.php @@ -26,7 +26,7 @@ public function handle() return; } - if (config('monica.customer_portal_url') == '') { + if (config('monica.customer_portal_url') === '') { return; } From c64e5d3e8366d86720184e7babf4c64c13751d19 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:23:49 -0400 Subject: [PATCH 19/41] Update app/Models/Account/Account.php Co-authored-by: Alexis Saettler --- app/Models/Account/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Account/Account.php b/app/Models/Account/Account.php index 7e1e1c41b3a..b1cea323444 100644 --- a/app/Models/Account/Account.php +++ b/app/Models/Account/Account.php @@ -83,7 +83,7 @@ class Account extends Model /** * The attributes that should be mutated to dates. * - * @var array + * @var array */ protected $dates = [ 'valid_until_at', From cc37c8012bf70a3f2b8e5a4fa473dcc4657117e6 Mon Sep 17 00:00:00 2001 From: Mazarin Date: Sun, 15 May 2022 07:31:13 -0400 Subject: [PATCH 20/41] Update app/Services/Account/Subscription/ActivateLicenceKey.php Co-authored-by: Alexis Saettler --- app/Services/Account/Subscription/ActivateLicenceKey.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 08180179060..d7405c9e896 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -6,14 +6,18 @@ use Illuminate\Support\Str; use App\Services\BaseService; use App\Models\Account\Account; +use App\Services\QueuableService; use Illuminate\Support\Facades\App; use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; +use App\Services\DispatchableService; use App\Exceptions\NoCustomerPortalSetException; use App\Exceptions\NoLicenceKeyEncryptionSetException; -class ActivateLicenceKey extends BaseService +class ActivateLicenceKey extends BaseService implements QueuableService { + use DispatchableService; + private Account $account; private array $data; private Response $response; From f22a05ee770d718e4eb77e89512bd54d99c46508 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sun, 15 May 2022 07:31:23 -0400 Subject: [PATCH 21/41] changes --- .../2022_03_08_115818_add_licence_keys_to_accounts.php | 6 +++--- resources/lang/en/settings.php | 2 ++ resources/views/layouts/skeleton.blade.php | 3 --- resources/views/settings/subscriptions/blank.blade.php | 6 +++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php index 1b1661a1c4e..fc5553e26d8 100644 --- a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php +++ b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php @@ -14,10 +14,10 @@ class AddLicenceKeysToAccounts extends Migration public function up() { Schema::table('accounts', function (Blueprint $table) { - $table->string('licence_key')->after('uuid')->nullable(); + $table->string('licence_key', 255)->after('uuid')->nullable(); $table->datetime('valid_until_at')->after('licence_key')->nullable(); - $table->string('purchaser_email')->after('valid_until_at')->nullable(); - $table->string('frequency')->after('purchaser_email')->nullable(); + $table->string('purchaser_email', 255)->after('valid_until_at')->nullable(); + $table->string('frequency', 15)->after('purchaser_email')->nullable(); }); } diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index acbd8855952..43f5b052bea 100644 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -225,6 +225,8 @@ 'subscriptions_plan_include1' => 'Included with your upgrade:', 'subscriptions_plan_include2' => 'Unlimited number of contacts • Unlimited number of users • Reminders by email • Import with vCard • Personalization of the contact sheet', 'subscriptions_plan_include3' => '100% of the profits go the development of this great open source project.', + 'subscriptions_plan_question' => 'Do you have your licence key?', + 'subscriptions_key_paste' => 'Please paste your licence key here', 'subscriptions_help_title' => 'Additional details you may be curious about', 'subscriptions_help_licencekey_title' => 'What is a licence key?', 'subscriptions_help_licencekey_desc' => 'A licence key is an unique identifier that you will get once you purchase a plan. It will be used to unlock all the paid features in your account. Licence keys are managed on https://customers.monicahq.com and you will need to create a new account on this site to get your licence key, that you will need to paste here.', diff --git a/resources/views/layouts/skeleton.blade.php b/resources/views/layouts/skeleton.blade.php index e18fe567270..3679ddf386a 100644 --- a/resources/views/layouts/skeleton.blade.php +++ b/resources/views/layouts/skeleton.blade.php @@ -48,9 +48,6 @@ @push('scripts') - @endpush - - @push('scripts') @endpush diff --git a/resources/views/settings/subscriptions/blank.blade.php b/resources/views/settings/subscriptions/blank.blade.php index f022646c9ca..fa8bd98754a 100644 --- a/resources/views/settings/subscriptions/blank.blade.php +++ b/resources/views/settings/subscriptions/blank.blade.php @@ -101,7 +101,7 @@

    -

    Do you have your licence key?

    +

    {{ trans('settings.subscriptions_plan_question') }}

    @include('partials.errors') @@ -109,9 +109,9 @@ @csrf
    - + -
    +
    From 8a01c7ede441fea8274a2d4f9cb37acdf6a9cc10 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Mon, 16 May 2022 10:19:17 +0200 Subject: [PATCH 22/41] adapt with last monicahq/customers changes --- app/Exceptions/MissingPrivateKeyException.php | 19 +++ .../NoCustomerPortalSecretsException.php | 9 ++ .../Settings/SubscriptionsController.php | 2 +- app/Jobs/Settings/CheckLicenceKeys.php | 2 +- app/Providers/AppServiceProvider.php | 1 - app/Providers/EncryptionServiceProvider.php | 58 +++++++++ .../Subscription/ActivateLicenceKey.php | 47 +++---- .../Subscription/CustomerPortalCall.php | 91 +++++++++++++ config/app.php | 1 + config/monica.php | 18 +-- ...08_115818_add_licence_keys_to_accounts.php | 4 +- tests/Feature/AccountSubscriptionTest.php | 121 ------------------ .../Subscription/ActivateLicenceKeyTest.php | 45 ++++--- .../Subscription/CustomerPortalCallTest.php | 77 +++++++++++ 14 files changed, 311 insertions(+), 184 deletions(-) create mode 100644 app/Exceptions/MissingPrivateKeyException.php create mode 100644 app/Exceptions/NoCustomerPortalSecretsException.php create mode 100755 app/Providers/EncryptionServiceProvider.php create mode 100644 app/Services/Account/Subscription/CustomerPortalCall.php create mode 100644 tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php diff --git a/app/Exceptions/MissingPrivateKeyException.php b/app/Exceptions/MissingPrivateKeyException.php new file mode 100644 index 00000000000..931cf99be28 --- /dev/null +++ b/app/Exceptions/MissingPrivateKeyException.php @@ -0,0 +1,19 @@ +execute([ + ActivateLicenceKey::dispatchSync([ 'account_id' => auth()->user()->account_id, 'licence_key' => $request->input('licence_key'), ]); diff --git a/app/Jobs/Settings/CheckLicenceKeys.php b/app/Jobs/Settings/CheckLicenceKeys.php index 174b914b345..b6365228591 100644 --- a/app/Jobs/Settings/CheckLicenceKeys.php +++ b/app/Jobs/Settings/CheckLicenceKeys.php @@ -35,7 +35,7 @@ public function handle() ->get(); foreach ($accounts as $account) { - app(ActivateLicenceKey::class)->execute([ + ActivateLicenceKey::dispatch([ 'account_id' => $account->id, 'licence_key' => $account->licence_key, ]); diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 9236cdf1aaa..e3c6a541831 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -231,6 +231,5 @@ public function register() \App\Services\Instance\AuditLog\LogAccountAction::class => \App\Services\Instance\AuditLog\LogAccountAction::class, \App\Services\User\UpdateViewPreference::class => \App\Services\User\UpdateViewPreference::class, \App\Services\User\AcceptPolicy::class => \App\Services\User\AcceptPolicy::class, - \App\Services\Account\Subscription\ActivateLicenceKey::class => \App\Services\Account\Subscription\ActivateLicenceKey::class, ]; } diff --git a/app/Providers/EncryptionServiceProvider.php b/app/Providers/EncryptionServiceProvider.php new file mode 100755 index 00000000000..f39020e489f --- /dev/null +++ b/app/Providers/EncryptionServiceProvider.php @@ -0,0 +1,58 @@ +app->singleton('license.encrypter', function ($app) { + $config = $app->make('config')->get('monica'); + + return new Encrypter($this->parseKey($config), $config['licence_cipher']); + }); + } + + /** + * Parse the encryption key. + * + * @param array $config + * @return string + */ + protected function parseKey(array $config) + { + if (Str::startsWith($key = $this->key($config), $prefix = 'base64:')) { + $key = base64_decode(Str::after($key, $prefix)); + } + + return $key; + } + + /** + * Extract the encryption key from the given configuration. + * + * @param array $config + * @return string + * + * @throws \App\Exceptions\MissingPrivateKeyException + */ + protected function key(array $config) + { + return tap($config['licence_private_key'], function ($key) { + if (empty($key)) { + throw new MissingPrivateKeyException(); + } + }); + } +} diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index d7405c9e896..c4f61dabe75 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -3,15 +3,10 @@ namespace App\Services\Account\Subscription; use Exception; -use Illuminate\Support\Str; use App\Services\BaseService; use App\Models\Account\Account; use App\Services\QueuableService; -use Illuminate\Support\Facades\App; -use Illuminate\Http\Client\Response; -use Illuminate\Support\Facades\Http; use App\Services\DispatchableService; -use App\Exceptions\NoCustomerPortalSetException; use App\Exceptions\NoLicenceKeyEncryptionSetException; class ActivateLicenceKey extends BaseService implements QueuableService @@ -20,7 +15,7 @@ class ActivateLicenceKey extends BaseService implements QueuableService private Account $account; private array $data; - private Response $response; + private int $status; /** * Get the validation rules that apply to the service. @@ -31,7 +26,7 @@ public function rules() { return [ 'account_id' => 'required|integer|exists:accounts,id', - 'licence_key' => 'required|string:255', + 'licence_key' => 'required|string:4096', ]; } @@ -42,7 +37,7 @@ public function rules() * @param array $data * @return void */ - public function execute(array $data): void + public function handle(array $data): void { $this->validate($data); $this->data = $data; @@ -56,52 +51,42 @@ public function execute(array $data): void private function validateEnvVariables(): void { - if (! config('monica.licence_key_encryption_key')) { - throw new NoLicenceKeyEncryptionSetException(); - } - - if (config('monica.customer_portal_url') === '') { - throw new NoCustomerPortalSetException(); + if (config('monica.licence_private_key') === null) { + throw new NoLicenceKeyEncryptionSetException; } } private function makeRequestToCustomerPortal(): void { - $url = config('monica.customer_portal_url').'/'.config('monica.customer_portal_secret_key').'/validate/'.$this->data['licence_key']; - - // necessary for testing purposes - if (App::environment('production')) { - $this->response = Http::get($url); - } else { - $this->response = Http::withOptions(['verify' => false])->get($url); - } + $this->status = app(CustomerPortalCall::class)->execute([ + 'licence_key' => $this->data['licence_key'] + ]); } private function checkResponseCode(): void { - if ($this->response->status() === 404) { + if ($this->status === 404) { throw new Exception(trans('settings.subscriptions_licence_key_does_not_exist')); } - if ($this->response->status() === 900) { + if ($this->status === 410) { throw new Exception(trans('settings.subscriptions_licence_key_invalid')); } - if ($this->response->status() !== 200) { + if ($this->status !== 200) { throw new Exception(trans('settings.subscriptions_licence_key_problem')); } } private function decodeAndStoreKey(): void { - $licenceKey = base64_decode($this->data['licence_key']); - $licenceKey = Str::replace('123', '', $licenceKey); - $array = json_decode($licenceKey, true); + $encrypter = app('license.encrypter'); + $licenceKey = $encrypter->decrypt($this->data['licence_key']); $this->account->licence_key = $this->data['licence_key']; - $this->account->valid_until_at = $array[0]['next_check_at']; - $this->account->purchaser_email = $array[0]['purchaser_email']; - $this->account->frequency = $array[0]['frequency']; + $this->account->valid_until_at = $licenceKey['next_check_at']; + $this->account->purchaser_email = $licenceKey['purchaser_email']; + $this->account->frequency = $licenceKey['frequency']; $this->account->save(); } } diff --git a/app/Services/Account/Subscription/CustomerPortalCall.php b/app/Services/Account/Subscription/CustomerPortalCall.php new file mode 100644 index 00000000000..0c8aa28f4df --- /dev/null +++ b/app/Services/Account/Subscription/CustomerPortalCall.php @@ -0,0 +1,91 @@ + 'required|string:4096', + ]; + } + + /** + * Check if the licence key given by the user is a valid licence key. + * If it is, activate the licence key and set the valid_until_at date. + * + * @param array $data + * @return int + */ + public function execute(array $data): int + { + $this->validate($data); + $this->data = $data; + + $this->validateEnvVariables(); + + $accessToken = $this->getAccessToken(); + $response = $this->makeRequestToCustomerPortal($accessToken); + + return $response->status(); + } + + private function validateEnvVariables(): void + { + if (config('monica.customer_portal_url') === '') { + throw new NoCustomerPortalSetException; + } + + if (config('monica.customer_portal_client_id') === null || config('monica.customer_portal_client_secret') === null) { + throw new NoCustomerPortalSecretsException; + } + } + + private function getAccessToken(): string + { + return Cache::remember('customer_portal_access_token', 604800, function () { + $url = config('monica.customer_portal_url').'/oauth/token'; + + $response = Http::asForm()->post($url, [ + 'grant_type' => 'client_credentials', + 'client_id' => config('monica.customer_portal_client_id'), + 'client_secret' => config('monica.customer_portal_client_secret'), + 'scope' => 'manage-key', + ]); + $response->throw(); + + $json = $response->json(); + if (! isset($json['access_token'])) { + throw new \Exception("No access_token"); + } + + return $json['access_token']; + }); + } + + private function makeRequestToCustomerPortal(string $accessToken): Response + { + $url = config('monica.customer_portal_url').'/api/validate'; + + return Http::withToken($accessToken) + ->acceptJson() + ->post($url, [ + 'licence_key' => $this->data['licence_key'] + ]); + } +} diff --git a/config/app.php b/config/app.php index ee5f50cc990..84fcd04c987 100644 --- a/config/app.php +++ b/config/app.php @@ -204,6 +204,7 @@ */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, + App\Providers\EncryptionServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\MacroServiceProvider::class, Vluzrmos\LanguageDetector\Providers\LanguageDetectorServiceProvider::class, diff --git a/config/monica.php b/config/monica.php index 259dcfe8bbb..5064acf84e7 100644 --- a/config/monica.php +++ b/config/monica.php @@ -296,6 +296,10 @@ */ 'customer_portal_url' => env('CUSTOMER_PORTAL_URL', ''), + 'customer_portal_client_id' => env('CUSTOMER_PORTAL_CLIENT_ID'), + + 'customer_portal_client_secret' => env('CUSTOMER_PORTAL_CLIENT_SECRET'), + /* |-------------------------------------------------------------------------- | Licence key encryption key @@ -305,16 +309,8 @@ | the key is generated. | */ - 'licence_key_encryption_key' => env('LICENCE_KEY_ENCRYPTION_KEY', null), - /* - |-------------------------------------------------------------------------- - | Secret key to communicate with the customer portal - |-------------------------------------------------------------------------- - | - | We need to communicate with the customer portal to check licence keys. - | This is done through an HTTP call that we need to secure. - | - */ - 'customer_portal_secret_key' => env('CUSTOMER_PORTAL_SECRET_KEY', null), + 'licence_private_key' => env('LICENCE_PRIVATE_KEY'), + + 'licence_cipher' => 'AES-256-GCM', ]; diff --git a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php index fc5553e26d8..349e67a3032 100644 --- a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php +++ b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php @@ -14,7 +14,7 @@ class AddLicenceKeysToAccounts extends Migration public function up() { Schema::table('accounts', function (Blueprint $table) { - $table->string('licence_key', 255)->after('uuid')->nullable(); + $table->string('licence_key', 4096)->after('uuid')->nullable(); $table->datetime('valid_until_at')->after('licence_key')->nullable(); $table->string('purchaser_email', 255)->after('valid_until_at')->nullable(); $table->string('frequency', 15)->after('purchaser_email')->nullable(); @@ -31,6 +31,8 @@ public function down() Schema::table('accounts', function (Blueprint $table) { $table->dropColumn('licence_keys'); $table->dropColumn('valid_until_at'); + $table->dropColumn('purchaser_email'); + $table->dropColumn('frequency'); }); } } diff --git a/tests/Feature/AccountSubscriptionTest.php b/tests/Feature/AccountSubscriptionTest.php index 26657933d03..dd84f119bd3 100644 --- a/tests/Feature/AccountSubscriptionTest.php +++ b/tests/Feature/AccountSubscriptionTest.php @@ -2,126 +2,13 @@ namespace Tests\Feature; -use Stripe\Plan; -use Stripe\Stripe; -use Stripe\Product; use Tests\FeatureTestCase; -use Illuminate\Support\Str; -use Laravel\Cashier\Subscription; use Illuminate\Foundation\Testing\DatabaseTransactions; class AccountSubscriptionTest extends FeatureTestCase { use DatabaseTransactions; - /** - * @var string - */ - protected static $stripePrefix = 'cashier-test-'; - - /** - * @var string - */ - protected static $productId; - - /** - * @var string - */ - protected static $monthlyPlanId; - - /** - * @var string - */ - protected static $annualPlanId; - - public function setUp(): void - { - parent::setUp(); - - if (! static::$productId) { - $this->markTestSkipped('Set STRIPE_SECRET to run this test.'); - } else { - config([ - 'services.stripe.secret' => env('STRIPE_SECRET'), - 'monica.requires_subscription' => true, - 'monica.paid_plan_monthly_friendly_name' => 'Monthly', - 'monica.paid_plan_monthly_id' => 'monthly', - 'monica.paid_plan_monthly_price' => 100, - 'monica.paid_plan_annual_friendly_name' => 'Annual', - 'monica.paid_plan_annual_id' => 'annual', - 'monica.paid_plan_annual_price' => 500, - ]); - } - } - - public static function setUpBeforeClass(): void - { - if (empty(env('STRIPE_SECRET'))) { - return; - } - - Stripe::setApiVersion('2019-03-14'); - Stripe::setApiKey(env('STRIPE_SECRET')); - - static::$productId = static::$stripePrefix.'product-'.Str::random(10); - static::$monthlyPlanId = static::$stripePrefix.'monthly-'.Str::random(10); - static::$annualPlanId = static::$stripePrefix.'annual-'.Str::random(10); - - Product::create([ - 'id' => static::$productId, - 'name' => 'Monica Test Product', - 'type' => 'service', - ]); - - Plan::create([ - 'id' => static::$monthlyPlanId, - 'nickname' => 'Monthly', - 'currency' => 'USD', - 'interval' => 'month', - 'billing_scheme' => 'per_unit', - 'amount' => 100, - 'product' => static::$productId, - ]); - Plan::create([ - 'id' => static::$annualPlanId, - 'nickname' => 'Annual', - 'currency' => 'USD', - 'interval' => 'year', - 'billing_scheme' => 'per_unit', - 'amount' => 500, - 'product' => static::$productId, - ]); - } - - public static function tearDownAfterClass(): void - { - parent::tearDownAfterClass(); - - if (static::$monthlyPlanId) { - static::deleteStripeResource(new Plan(static::$monthlyPlanId)); - static::$monthlyPlanId = null; - } - if (static::$annualPlanId) { - static::deleteStripeResource(new Plan(static::$annualPlanId)); - static::$annualPlanId = null; - } - if (static::$productId) { - static::deleteStripeResource(new Product(static::$productId)); - static::$productId = null; - } - } - - protected static function deleteStripeResource($resource) - { - try { - if (method_exists($resource, 'delete')) { - $resource->delete(); - } - } catch (\Stripe\Exception\ApiErrorException $e) { - // - } - } - public function test_it_sees_the_plan_names() { $user = $this->signin(); @@ -135,14 +22,6 @@ public function test_it_get_subscription_page() { $user = $this->signin(); - factory(Subscription::class)->create([ - 'account_id' => $user->account_id, - 'name' => 'Annual', - 'stripe_plan' => 'annual', - 'stripe_id' => 'sub_X', - 'quantity' => 1, - ]); - $response = $this->get('/settings/subscriptions'); $response->assertSee('You are on the Annual plan. Thanks so much for being a subscriber.'); diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php index f82fafa4167..bb3a1a9fa65 100644 --- a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit\Services\Account\Subscription; +use App\Exceptions\NoLicenceKeyEncryptionSetException; use Exception; use Tests\TestCase; use App\Models\Account\Account; @@ -9,6 +10,8 @@ use Illuminate\Validation\ValidationException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\ActivateLicenceKey; +use App\Services\Account\Subscription\CustomerPortalCall; +use Mockery\MockInterface; class ActivateLicenceKeyTest extends TestCase { @@ -17,10 +20,9 @@ class ActivateLicenceKeyTest extends TestCase /** @test */ public function it_activates_a_licence_key() { - config(['monica.licence_key_encryption_key' => '123']); - Http::fake(); + config(['monica.licence_private_key' => 'base64:CiZYhXuxFaXsYWOTw8o6C82rqiZkphLg+N6fVep2l0M=']); - $key = 'W3siZnJlcXVlbmN5IjoibW9udGhseSIsInB1cmNoYXNlcl9lbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsIm5leHRfY2hlY2tfYXQiOiIyMDIyLTA0LTAzVDAwOjAwOjAwLjAwMDAwMFoifV0='; + $key = 'eyJpdiI6IjJ5clV4N3hlaThIMGtsckgiLCJ2YWx1ZSI6IkdIUWd4aFM4OWlHL2V3SHF0M1VOazVYTjBaN2c4RGpRUDZtN0VNejhGL0YzZGF6bmFBNnBzK3lUT0VVVXFIaE80SlZ3RmRRK3J4UTRBQU5XU2lUS3JhRHQ0d1paYUIrNGM0VUg2ZzBNU3Y4MjlzQ0d4N2pTZGlPY3E5UWFMRGJCSXdZSnN6a1MwYVg5RFBaQ01jMGtpMzhubnVFbmV5TXB3Zz09IiwibWFjIjoiIiwidGFnIjoiWVZlUjgrQU8yUlBCd1BaTDUxb1JJZz09In0='; $account = factory(Account::class)->create([]); $request = [ @@ -28,12 +30,19 @@ public function it_activates_a_licence_key() 'licence_key' => $key, ]; - app(ActivateLicenceKey::class)->execute($request); + $this->mock(CustomerPortalCall::class, function (MockInterface $mock) use ($key) { + $mock->shouldReceive('execute') + ->once() + ->with(['licence_key' => $key]) + ->andReturn(200); + }); + + app(ActivateLicenceKey::class)->handle($request); $this->assertDatabaseHas('accounts', [ 'id' => $account->id, - 'licence_key' => 'W3siZnJlcXVlbmN5IjoibW9udGhseSIsInB1cmNoYXNlcl9lbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsIm5leHRfY2hlY2tfYXQiOiIyMDIyLTA0LTAzVDAwOjAwOjAwLjAwMDAwMFoifV0=', - 'valid_until_at' => '2022-04-03 00:00:00', + 'licence_key' => $key, + 'valid_until_at' => '2022-04-03', 'purchaser_email' => 'admin@admin.com', 'frequency' => 'monthly', ]); @@ -45,17 +54,13 @@ public function it_fails_if_wrong_parameters_are_given() $request = []; $this->expectException(ValidationException::class); - app(ActivateLicenceKey::class)->execute($request); + app(ActivateLicenceKey::class)->handle($request); } /** @test */ public function it_fails_if_the_licence_key_does_not_exist() { - $this->expectException(Exception::class); - - Http::fake(function ($request) { - return Http::response('', 404); - }); + $this->expectException(ValidationException::class); $account = factory(Account::class)->create([]); @@ -64,19 +69,25 @@ public function it_fails_if_the_licence_key_does_not_exist() 'licence_key' => '', ]; - app(ActivateLicenceKey::class)->execute($request); + app(ActivateLicenceKey::class)->handle($request); } /** @test */ public function it_fails_if_the_licence_key_is_not_valid_anymore() { + config(['monica.licence_private_key' => 'base64:4IKtoOuRUWQLk2mdQ3MmM7VEr6dvP0IJWoijGk6NpRA=']); + $this->expectException(Exception::class); - Http::fake(function ($request) { - return Http::response('', 900); + $key = 'eyJpdiI6IjJ5clV4N3hlaThIMGtsckgiLCJ2YWx1ZSI6IkdIUWd4aFM4OWlHL2V3SHF0M1VOazVYTjBaN2c4RGpRUDZtN0VNejhGL0YzZGF6bmFBNnBzK3lUT0VVVXFIaE80SlZ3RmRRK3J4UTRBQU5XU2lUS3JhRHQ0d1paYUIrNGM0VUg2ZzBNU3Y4MjlzQ0d4N2pTZGlPY3E5UWFMRGJCSXdZSnN6a1MwYVg5RFBaQ01jMGtpMzhubnVFbmV5TXB3Zz09IiwibWFjIjoiIiwidGFnIjoiWVZlUjgrQU8yUlBCd1BaTDUxb1JJZz09In0='; + + $this->mock(CustomerPortalCall::class, function (MockInterface $mock) use ($key) { + $mock->shouldReceive('execute') + ->once() + ->with(['licence_key' => $key]) + ->andReturn(410); }); - $key = 'W3siZnJlcXVlbmN5IjoibW9udGhseSIsInB1cmNoYXNlcl9lbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsIm5leHRfY2hlY2tfYXQiOiIyMDIyLTA0LTAzVDAwOjAwOjAwLjAwMDAwMFoifV0='; $account = factory(Account::class)->create([]); $request = [ @@ -84,6 +95,6 @@ public function it_fails_if_the_licence_key_is_not_valid_anymore() 'licence_key' => $key, ]; - app(ActivateLicenceKey::class)->execute($request); + app(ActivateLicenceKey::class)->handle($request); } } diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php new file mode 100644 index 00000000000..e2d9e1363c6 --- /dev/null +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -0,0 +1,77 @@ + 'https://fake.test']); + config(['monica.customer_portal_client_id' => '1']); + config(['monica.customer_portal_client_secret' => '1']); + + Cache::flush(); + + Http::fake([ + 'https://fake.test/oauth/token' => Http::response(['access_token' => '123']), + 'https://fake.test/api/validate' => Http::response([], 200), + ]); + + $request = [ + 'licence_key' => 'key', + ]; + + $status = app(CustomerPortalCall::class)->execute($request); + + $this->assertEquals(200, $status); + + Http::assertSentInOrder([ + function ($request, $response) { + $this->assertEquals('POST', $request->method()); + $this->assertEquals('https://fake.test/oauth/token', $request->url()); + $this->assertEquals('grant_type=client_credentials&client_id=1&client_secret=1&scope=manage-key', $request->body()); + $this->assertEquals('{"access_token":"123"}', $response->body()); + return true; + }, + function ($request, $response) { + $this->assertEquals('POST', $request->method()); + $this->assertEquals('https://fake.test/api/validate', $request->url()); + $this->assertEquals('{"licence_key":"key"}', $request->body()); + $this->assertEquals(['Bearer 123'], $request->header('Authorization')); + $this->assertEquals(200, $response->status()); + return true; + }, + ]); + } + + /** @test */ + public function it_fails_if_wrong_parameters_are_given() + { + $request = []; + + $this->expectException(ValidationException::class); + app(CustomerPortalCall::class)->execute($request); + } + + /** @test */ + public function it_fails_if_the_licence_key_does_not_exist() + { + $this->expectException(ValidationException::class); + + $request = [ + 'licence_key' => '', + ]; + + app(CustomerPortalCall::class)->execute($request); + } +} From 25f022cab771da5f470bf6204bcca97d66e052a2 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 16 May 2022 08:19:46 +0000 Subject: [PATCH 23/41] Apply fixes from StyleCI --- app/Providers/EncryptionServiceProvider.php | 6 +++--- app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- app/Services/Account/Subscription/CustomerPortalCall.php | 8 ++++---- .../Account/Subscription/ActivateLicenceKeyTest.php | 4 +--- .../Account/Subscription/CustomerPortalCallTest.php | 4 +++- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/Providers/EncryptionServiceProvider.php b/app/Providers/EncryptionServiceProvider.php index f39020e489f..279f2e6feda 100755 --- a/app/Providers/EncryptionServiceProvider.php +++ b/app/Providers/EncryptionServiceProvider.php @@ -2,11 +2,11 @@ namespace App\Providers; -use App\Exceptions\MissingPrivateKeyException; -use Illuminate\Encryption\Encrypter; -use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; use function Safe\base64_decode; +use Illuminate\Encryption\Encrypter; +use Illuminate\Support\ServiceProvider; +use App\Exceptions\MissingPrivateKeyException; class EncryptionServiceProvider extends ServiceProvider { diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index c4f61dabe75..3be4e67edfa 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -59,7 +59,7 @@ private function validateEnvVariables(): void private function makeRequestToCustomerPortal(): void { $this->status = app(CustomerPortalCall::class)->execute([ - 'licence_key' => $this->data['licence_key'] + 'licence_key' => $this->data['licence_key'], ]); } diff --git a/app/Services/Account/Subscription/CustomerPortalCall.php b/app/Services/Account/Subscription/CustomerPortalCall.php index 0c8aa28f4df..6d28c29fceb 100644 --- a/app/Services/Account/Subscription/CustomerPortalCall.php +++ b/app/Services/Account/Subscription/CustomerPortalCall.php @@ -2,12 +2,12 @@ namespace App\Services\Account\Subscription; -use App\Exceptions\NoCustomerPortalSecretsException; use App\Services\BaseService; use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; -use App\Exceptions\NoCustomerPortalSetException; use Illuminate\Support\Facades\Cache; +use App\Exceptions\NoCustomerPortalSetException; +use App\Exceptions\NoCustomerPortalSecretsException; class CustomerPortalCall extends BaseService { @@ -71,7 +71,7 @@ private function getAccessToken(): string $json = $response->json(); if (! isset($json['access_token'])) { - throw new \Exception("No access_token"); + throw new \Exception('No access_token'); } return $json['access_token']; @@ -85,7 +85,7 @@ private function makeRequestToCustomerPortal(string $accessToken): Response return Http::withToken($accessToken) ->acceptJson() ->post($url, [ - 'licence_key' => $this->data['licence_key'] + 'licence_key' => $this->data['licence_key'], ]); } } diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php index bb3a1a9fa65..4b8728f933a 100644 --- a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -2,16 +2,14 @@ namespace Tests\Unit\Services\Account\Subscription; -use App\Exceptions\NoLicenceKeyEncryptionSetException; use Exception; use Tests\TestCase; +use Mockery\MockInterface; use App\Models\Account\Account; -use Illuminate\Support\Facades\Http; use Illuminate\Validation\ValidationException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\ActivateLicenceKey; use App\Services\Account\Subscription\CustomerPortalCall; -use Mockery\MockInterface; class ActivateLicenceKeyTest extends TestCase { diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php index e2d9e1363c6..6814c2eff2c 100644 --- a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -4,10 +4,10 @@ use Tests\TestCase; use Illuminate\Support\Facades\Http; +use Illuminate\Support\Facades\Cache; use Illuminate\Validation\ValidationException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\CustomerPortalCall; -use Illuminate\Support\Facades\Cache; class CustomerPortalCallTest extends TestCase { @@ -41,6 +41,7 @@ function ($request, $response) { $this->assertEquals('https://fake.test/oauth/token', $request->url()); $this->assertEquals('grant_type=client_credentials&client_id=1&client_secret=1&scope=manage-key', $request->body()); $this->assertEquals('{"access_token":"123"}', $response->body()); + return true; }, function ($request, $response) { @@ -49,6 +50,7 @@ function ($request, $response) { $this->assertEquals('{"licence_key":"key"}', $request->body()); $this->assertEquals(['Bearer 123'], $request->header('Authorization')); $this->assertEquals(200, $response->status()); + return true; }, ]); From 4c74f4faf0ec062e077d25fead43753d132cfa90 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Mon, 16 May 2022 10:38:00 +0200 Subject: [PATCH 24/41] add tests --- .../Subscription/ActivateLicenceKeyTest.php | 20 ++++++- .../Subscription/CustomerPortalCallTest.php | 52 ++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php index bb3a1a9fa65..ab8e8adc7cf 100644 --- a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -58,7 +58,7 @@ public function it_fails_if_wrong_parameters_are_given() } /** @test */ - public function it_fails_if_the_licence_key_does_not_exist() + public function it_fails_if_the_licence_key_is_empty() { $this->expectException(ValidationException::class); @@ -72,6 +72,24 @@ public function it_fails_if_the_licence_key_does_not_exist() app(ActivateLicenceKey::class)->handle($request); } + + /** @test */ + public function it_fails_if_the_private_key_is_not_set() + { + config(['monica.licence_private_key' => null]); + + $this->expectException(NoLicenceKeyEncryptionSetException::class); + + $account = factory(Account::class)->create([]); + + $request = [ + 'account_id' => $account->id, + 'licence_key' => 'test', + ]; + + app(ActivateLicenceKey::class)->handle($request); + } + /** @test */ public function it_fails_if_the_licence_key_is_not_valid_anymore() { diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php index e2d9e1363c6..f402327872b 100644 --- a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -2,6 +2,8 @@ namespace Tests\Unit\Services\Account\Subscription; +use App\Exceptions\NoCustomerPortalSecretsException; +use App\Exceptions\NoCustomerPortalSetException; use Tests\TestCase; use Illuminate\Support\Facades\Http; use Illuminate\Validation\ValidationException; @@ -64,7 +66,7 @@ public function it_fails_if_wrong_parameters_are_given() } /** @test */ - public function it_fails_if_the_licence_key_does_not_exist() + public function it_fails_if_the_licence_key_is_empty() { $this->expectException(ValidationException::class); @@ -74,4 +76,52 @@ public function it_fails_if_the_licence_key_does_not_exist() app(CustomerPortalCall::class)->execute($request); } + + /** @test */ + public function it_fails_if_the_customer_portal_is_not_set() + { + config(['monica.customer_portal_url' => '']); + config(['monica.customer_portal_client_id' => '1']); + config(['monica.customer_portal_client_secret' => '1']); + + $this->expectException(NoCustomerPortalSetException::class); + + $request = [ + 'licence_key' => 'test', + ]; + + app(CustomerPortalCall::class)->execute($request); + } + + /** @test */ + public function it_fails_if_the_client_id_is_not_set() + { + config(['monica.customer_portal_url' => 'https://fake.test']); + config(['monica.customer_portal_client_id' => null]); + config(['monica.customer_portal_client_secret' => '1']); + + $this->expectException(NoCustomerPortalSecretsException::class); + + $request = [ + 'licence_key' => 'test', + ]; + + app(CustomerPortalCall::class)->execute($request); + } + + /** @test */ + public function it_fails_if_the_client_secret_is_not_set() + { + config(['monica.customer_portal_url' => 'https://fake.test']); + config(['monica.customer_portal_client_id' => '1']); + config(['monica.customer_portal_client_secret' => null]); + + $this->expectException(NoCustomerPortalSecretsException::class); + + $request = [ + 'licence_key' => 'test', + ]; + + app(CustomerPortalCall::class)->execute($request); + } } From b5615db28e3b910de152c464a4a24f1024c133a8 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 16 May 2022 08:38:12 +0000 Subject: [PATCH 25/41] Apply fixes from StyleCI --- .../Services/Account/Subscription/ActivateLicenceKeyTest.php | 1 - .../Services/Account/Subscription/CustomerPortalCallTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php index 098029d4d36..122c992d482 100644 --- a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -70,7 +70,6 @@ public function it_fails_if_the_licence_key_is_empty() app(ActivateLicenceKey::class)->handle($request); } - /** @test */ public function it_fails_if_the_private_key_is_not_set() { diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php index b913c7f09d2..2a67bac8bf0 100644 --- a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -2,12 +2,12 @@ namespace Tests\Unit\Services\Account\Subscription; -use App\Exceptions\NoCustomerPortalSecretsException; -use App\Exceptions\NoCustomerPortalSetException; use Tests\TestCase; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Cache; use Illuminate\Validation\ValidationException; +use App\Exceptions\NoCustomerPortalSetException; +use App\Exceptions\NoCustomerPortalSecretsException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\CustomerPortalCall; From 94a31599bb6a25dcd4bd0f75bf2ed336eb9bee60 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Mon, 16 May 2022 14:20:59 +0200 Subject: [PATCH 26/41] more tests --- .../CustomerPortalWrongCredentials.php | 19 +++++ .../LicenceKeyDontExistException.php | 19 +++++ app/Exceptions/LicenceKeyErrorException.php | 19 +++++ app/Exceptions/LicenceKeyInvalidException.php | 19 +++++ .../NoCustomerPortalSecretsException.php | 10 +++ .../NoCustomerPortalSetException.php | 10 +++ .../NoLicenceKeyEncryptionSetException.php | 10 +++ .../Subscription/ActivateLicenceKey.php | 11 ++- .../Subscription/CustomerPortalCall.php | 8 +- .../Subscription/ActivateLicenceKeyTest.php | 65 ++++++++++++++-- .../Subscription/CustomerPortalCallTest.php | 75 +++++++++++++++++++ 11 files changed, 252 insertions(+), 13 deletions(-) create mode 100644 app/Exceptions/CustomerPortalWrongCredentials.php create mode 100644 app/Exceptions/LicenceKeyDontExistException.php create mode 100644 app/Exceptions/LicenceKeyErrorException.php create mode 100644 app/Exceptions/LicenceKeyInvalidException.php diff --git a/app/Exceptions/CustomerPortalWrongCredentials.php b/app/Exceptions/CustomerPortalWrongCredentials.php new file mode 100644 index 00000000000..89a189444d0 --- /dev/null +++ b/app/Exceptions/CustomerPortalWrongCredentials.php @@ -0,0 +1,19 @@ +status === 404) { - throw new Exception(trans('settings.subscriptions_licence_key_does_not_exist')); + throw new LicenceKeyDontExistException; } if ($this->status === 410) { - throw new Exception(trans('settings.subscriptions_licence_key_invalid')); + throw new LicenceKeyInvalidException; } if ($this->status !== 200) { - throw new Exception(trans('settings.subscriptions_licence_key_problem')); + throw new LicenceKeyErrorException; } } diff --git a/app/Services/Account/Subscription/CustomerPortalCall.php b/app/Services/Account/Subscription/CustomerPortalCall.php index 6d28c29fceb..a52a144493b 100644 --- a/app/Services/Account/Subscription/CustomerPortalCall.php +++ b/app/Services/Account/Subscription/CustomerPortalCall.php @@ -7,6 +7,7 @@ use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Cache; use App\Exceptions\NoCustomerPortalSetException; +use App\Exceptions\CustomerPortalWrongCredentials; use App\Exceptions\NoCustomerPortalSecretsException; class CustomerPortalCall extends BaseService @@ -58,7 +59,7 @@ private function validateEnvVariables(): void private function getAccessToken(): string { - return Cache::remember('customer_portal_access_token', 604800, function () { + return Cache::remember('customer_portal.access_token', 31449600 /* 364 days */, function () { $url = config('monica.customer_portal_url').'/oauth/token'; $response = Http::asForm()->post($url, [ @@ -67,11 +68,10 @@ private function getAccessToken(): string 'client_secret' => config('monica.customer_portal_client_secret'), 'scope' => 'manage-key', ]); - $response->throw(); $json = $response->json(); - if (! isset($json['access_token'])) { - throw new \Exception('No access_token'); + if ($response->failed() || ! isset($json['access_token'])) { + throw new CustomerPortalWrongCredentials(); } return $json['access_token']; diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php index 122c992d482..6aa3ee0d702 100644 --- a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -2,11 +2,14 @@ namespace Tests\Unit\Services\Account\Subscription; -use Exception; use Tests\TestCase; use Mockery\MockInterface; use App\Models\Account\Account; +use App\Exceptions\LicenceKeyErrorException; +use App\Exceptions\LicenceKeyInvalidException; use Illuminate\Validation\ValidationException; +use App\Exceptions\LicenceKeyDontExistException; +use App\Exceptions\NoLicenceKeyEncryptionSetException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\ActivateLicenceKey; use App\Services\Account\Subscription\CustomerPortalCall; @@ -71,7 +74,7 @@ public function it_fails_if_the_licence_key_is_empty() } /** @test */ - public function it_fails_if_the_private_key_is_not_set() + public function it_fails_if_private_key_is_not_set() { config(['monica.licence_private_key' => null]); @@ -87,14 +90,40 @@ public function it_fails_if_the_private_key_is_not_set() app(ActivateLicenceKey::class)->handle($request); } + /** @test */ + public function it_fails_if_the_licence_key_does_not_exist() + { + config(['monica.licence_private_key' => 'x']); + + $this->expectException(LicenceKeyDontExistException::class); + + $key = 'x'; + + $this->mock(CustomerPortalCall::class, function (MockInterface $mock) use ($key) { + $mock->shouldReceive('execute') + ->once() + ->with(['licence_key' => $key]) + ->andReturn(404); + }); + + $account = factory(Account::class)->create([]); + + $request = [ + 'account_id' => $account->id, + 'licence_key' => $key, + ]; + + app(ActivateLicenceKey::class)->handle($request); + } + /** @test */ public function it_fails_if_the_licence_key_is_not_valid_anymore() { - config(['monica.licence_private_key' => 'base64:4IKtoOuRUWQLk2mdQ3MmM7VEr6dvP0IJWoijGk6NpRA=']); + config(['monica.licence_private_key' => 'x']); - $this->expectException(Exception::class); + $this->expectException(LicenceKeyInvalidException::class); - $key = 'eyJpdiI6IjJ5clV4N3hlaThIMGtsckgiLCJ2YWx1ZSI6IkdIUWd4aFM4OWlHL2V3SHF0M1VOazVYTjBaN2c4RGpRUDZtN0VNejhGL0YzZGF6bmFBNnBzK3lUT0VVVXFIaE80SlZ3RmRRK3J4UTRBQU5XU2lUS3JhRHQ0d1paYUIrNGM0VUg2ZzBNU3Y4MjlzQ0d4N2pTZGlPY3E5UWFMRGJCSXdZSnN6a1MwYVg5RFBaQ01jMGtpMzhubnVFbmV5TXB3Zz09IiwibWFjIjoiIiwidGFnIjoiWVZlUjgrQU8yUlBCd1BaTDUxb1JJZz09In0='; + $key = 'x'; $this->mock(CustomerPortalCall::class, function (MockInterface $mock) use ($key) { $mock->shouldReceive('execute') @@ -112,4 +141,30 @@ public function it_fails_if_the_licence_key_is_not_valid_anymore() app(ActivateLicenceKey::class)->handle($request); } + + /** @test */ + public function it_fails_if_there_is_an_error_during_validation() + { + config(['monica.licence_private_key' => 'x']); + + $this->expectException(LicenceKeyErrorException::class); + + $key = 'x'; + + $this->mock(CustomerPortalCall::class, function (MockInterface $mock) use ($key) { + $mock->shouldReceive('execute') + ->once() + ->with(['licence_key' => $key]) + ->andReturn(500); + }); + + $account = factory(Account::class)->create([]); + + $request = [ + 'account_id' => $account->id, + 'licence_key' => $key, + ]; + + app(ActivateLicenceKey::class)->handle($request); + } } diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php index 2a67bac8bf0..daa955e7b6d 100644 --- a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit\Services\Account\Subscription; +use App\Exceptions\CustomerPortalWrongCredentials; use Tests\TestCase; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Cache; @@ -10,6 +11,8 @@ use App\Exceptions\NoCustomerPortalSecretsException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\CustomerPortalCall; +use Exception; +use Illuminate\Http\Client\RequestException; class CustomerPortalCallTest extends TestCase { @@ -126,4 +129,76 @@ public function it_fails_if_the_client_secret_is_not_set() app(CustomerPortalCall::class)->execute($request); } + + /** @test */ + public function it_stores_access_token_into_cache() + { + config(['monica.customer_portal_url' => 'https://fake.test']); + config(['monica.customer_portal_client_id' => '1']); + config(['monica.customer_portal_client_secret' => '1']); + + Cache::flush(); + + $this->assertFalse(Cache::has('customer_portal.access_token')); + + Http::fake([ + 'https://fake.test/oauth/token' => Http::response(['access_token' => '123']), + 'https://fake.test/api/validate' => Http::response([], 200), + ]); + + $request = [ + 'licence_key' => 'key', + ]; + + app(CustomerPortalCall::class)->execute($request); + + $this->assertTrue(Cache::has('customer_portal.access_token')); + } + + /** @test */ + public function it_throw_an_exception_if_no_access_token() + { + config(['monica.customer_portal_url' => 'https://fake.test']); + config(['monica.customer_portal_client_id' => '1']); + config(['monica.customer_portal_client_secret' => '1']); + + Cache::flush(); + + $this->assertFalse(Cache::has('customer_portal.access_token')); + + Http::fake([ + 'https://fake.test/oauth/token' => Http::response([]), + 'https://fake.test/api/validate' => Http::response([], 200), + ]); + + $request = [ + 'licence_key' => 'key', + ]; + + $this->expectException(CustomerPortalWrongCredentials::class); + app(CustomerPortalCall::class)->execute($request); + } + + /** @test */ + public function it_throw_an_exception_if_oauth_token_send_bad_status() + { + config(['monica.customer_portal_url' => 'https://fake.test']); + config(['monica.customer_portal_client_id' => '1']); + config(['monica.customer_portal_client_secret' => '1']); + + Cache::flush(); + + $this->assertFalse(Cache::has('customer_portal.access_token')); + + Http::fake([ + 'https://fake.test/oauth/token' => Http::response([], 500), + ]); + + $request = [ + 'licence_key' => 'key', + ]; + + $this->expectException(CustomerPortalWrongCredentials::class); + app(CustomerPortalCall::class)->execute($request); + } } From 2df3c55891a73a7cc8eef2d83d28f9c32025523e Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 16 May 2022 12:21:37 +0000 Subject: [PATCH 27/41] Apply fixes from StyleCI --- app/Services/Account/Subscription/ActivateLicenceKey.php | 3 +-- .../Services/Account/Subscription/CustomerPortalCallTest.php | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 539230cda69..51f203bb589 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -6,10 +6,9 @@ use App\Models\Account\Account; use App\Services\QueuableService; use App\Services\DispatchableService; -use App\Exceptions\ActivateLicenceKeyException; -use App\Exceptions\LicenceKeyDontExistException; use App\Exceptions\LicenceKeyErrorException; use App\Exceptions\LicenceKeyInvalidException; +use App\Exceptions\LicenceKeyDontExistException; use App\Exceptions\NoLicenceKeyEncryptionSetException; class ActivateLicenceKey extends BaseService implements QueuableService diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php index daa955e7b6d..934d55e17d4 100644 --- a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -2,17 +2,15 @@ namespace Tests\Unit\Services\Account\Subscription; -use App\Exceptions\CustomerPortalWrongCredentials; use Tests\TestCase; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Cache; use Illuminate\Validation\ValidationException; use App\Exceptions\NoCustomerPortalSetException; +use App\Exceptions\CustomerPortalWrongCredentials; use App\Exceptions\NoCustomerPortalSecretsException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\CustomerPortalCall; -use Exception; -use Illuminate\Http\Client\RequestException; class CustomerPortalCallTest extends TestCase { From 0af744ecd59319980379ccffca37d9f03b93f30e Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Fri, 20 May 2022 08:27:20 +0200 Subject: [PATCH 28/41] split decodeAndStoreKey --- .../Account/Subscription/ActivateLicenceKey.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 51f203bb589..8f11f88f2a7 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -48,7 +48,7 @@ public function handle(array $data): void $this->validateEnvVariables(); $this->makeRequestToCustomerPortal(); $this->checkResponseCode(); - $this->decodeAndStoreKey(); + $this->store(); } private function validateEnvVariables(): void @@ -80,10 +80,9 @@ private function checkResponseCode(): void } } - private function decodeAndStoreKey(): void + private function store(): void { - $encrypter = app('license.encrypter'); - $licenceKey = $encrypter->decrypt($this->data['licence_key']); + $licenceKey = $this->decodeKey(); $this->account->licence_key = $this->data['licence_key']; $this->account->valid_until_at = $licenceKey['next_check_at']; @@ -91,4 +90,10 @@ private function decodeAndStoreKey(): void $this->account->frequency = $licenceKey['frequency']; $this->account->save(); } + + private function decodeKey(): array + { + $encrypter = app('license.encrypter'); + return $encrypter->decrypt($this->data['licence_key']); + } } From 0b68ccafb2dd2af2a196d562ee35a22deedbc2a4 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 20 May 2022 06:27:35 +0000 Subject: [PATCH 29/41] Apply fixes from StyleCI --- app/Services/Account/Subscription/ActivateLicenceKey.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 8f11f88f2a7..c15ca261a58 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -94,6 +94,7 @@ private function store(): void private function decodeKey(): array { $encrypter = app('license.encrypter'); + return $encrypter->decrypt($this->data['licence_key']); } } From 57f569b8f6a4fa49ce69884e206ef934aae25993 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Tue, 23 Aug 2022 07:21:18 -0400 Subject: [PATCH 30/41] Update AppServiceProvider.php --- app/Providers/AppServiceProvider.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 38d7736d91b..b56501894ea 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -86,8 +86,6 @@ public function boot() Schema::defaultStringLength(191); } - Cashier::useCustomerModel(\App\Models\Account\Account::class); - VerifyEmail::toMailUsing(function ($user, $verificationUrl) { return EmailMessaging::verifyEmailMail($user, $verificationUrl); }); From 44ae474c258d683a4c50c38c42a85c148b90ea9a Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Tue, 23 Aug 2022 07:44:59 -0400 Subject: [PATCH 31/41] Update AccountSubscriptionTest.php --- tests/Feature/AccountSubscriptionTest.php | 35 ----------------------- 1 file changed, 35 deletions(-) diff --git a/tests/Feature/AccountSubscriptionTest.php b/tests/Feature/AccountSubscriptionTest.php index dd84f119bd3..3c243ab0b14 100644 --- a/tests/Feature/AccountSubscriptionTest.php +++ b/tests/Feature/AccountSubscriptionTest.php @@ -35,39 +35,4 @@ public function test_it_get_blank_page_on_update_if_not_subscribed() $response->assertSee('Upgrade Monica today and have more meaningful relationships.'); } - - public function test_it_get_subscription_update() - { - $user = $this->signin(); - $user->email = 'test_it_subscribe@monica-test.com'; - $user->save(); - - $response = $this->post('/settings/subscriptions/processPayment', [ - 'payment_method' => 'pm_card_visa', - 'plan' => 'annual', - ]); - - $response = $this->get('/settings/subscriptions/update'); - - $response->assertSee('Monthly – $1.00'); - $response->assertSee('Annual – $5.00'); - } - - public function test_it_process_subscription_update() - { - $user = $this->signin(); - $user->email = 'test_it_subscribe@monica-test.com'; - $user->save(); - - $response = $this->post('/settings/subscriptions/processPayment', [ - 'payment_method' => 'pm_card_visa', - 'plan' => 'monthly', - ]); - - $response = $this->followingRedirects()->post('/settings/subscriptions/update', [ - 'frequency' => 'annual', - ]); - - $response->assertSee('You are on the Annual plan.'); - } } From ecb82c15a7cfe5bf26dcd1082ba55c06d147f61c Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Wed, 24 Aug 2022 08:27:55 -0400 Subject: [PATCH 32/41] fixes --- phpstan.neon | 2 - tests/Unit/Helpers/InstanceHelperTest.php | 66 ----------------------- 2 files changed, 68 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 063921b2d1e..b3314a83142 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -34,8 +34,6 @@ parameters: path: */Traits/Searchable.php - message: '#Access to an undefined property Faker\\Generator::\$state\.#' path: */Console/Commands/SetupTest.php - - message: '#Access to an undefined property Stripe\\Subscription::\$plan\.#' - path: */Helpers/InstanceHelper.php - message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::recurring\(\)\.#' path: */Traits/Subscription.php - message: '#Function dns_get_record is unsafe to use\. It can return FALSE instead of throwing an exception\. Please add ''use function Safe\\dns_get_record;'' at the beginning of the file to use the variant provided by the ''thecodingmachine/safe'' library\.#' diff --git a/tests/Unit/Helpers/InstanceHelperTest.php b/tests/Unit/Helpers/InstanceHelperTest.php index f280df85c66..ae12557894e 100644 --- a/tests/Unit/Helpers/InstanceHelperTest.php +++ b/tests/Unit/Helpers/InstanceHelperTest.php @@ -13,72 +13,6 @@ class InstanceHelperTest extends TestCase { use DatabaseTransactions; - /** @test */ - public function it_fetches_the_monthly_plan_information() - { - config(['monica.paid_plan_monthly_friendly_name' => 'Monthly']); - config(['monica.paid_plan_monthly_id' => 'monthly']); - config(['monica.paid_plan_monthly_price' => 1000]); - - $this->assertEquals( - 'monthly', - InstanceHelper::getPlanInformationFromConfig('monthly')['type'] - ); - - $this->assertEquals( - 'Monthly', - InstanceHelper::getPlanInformationFromConfig('monthly')['name'] - ); - - $this->assertEquals( - 'monthly', - InstanceHelper::getPlanInformationFromConfig('monthly')['id'] - ); - - $this->assertEquals( - 1000, - InstanceHelper::getPlanInformationFromConfig('monthly')['price'] - ); - - $this->assertEquals( - '$10.00', - InstanceHelper::getPlanInformationFromConfig('monthly')['friendlyPrice'] - ); - } - - /** @test */ - public function it_fetches_the_annually_plan_information() - { - config(['monica.paid_plan_annual_friendly_name' => 'Annual']); - config(['monica.paid_plan_annual_id' => 'annual']); - config(['monica.paid_plan_annual_price' => 1000]); - - $this->assertEquals( - 'annual', - InstanceHelper::getPlanInformationFromConfig('annual')['type'] - ); - - $this->assertEquals( - 'Annual', - InstanceHelper::getPlanInformationFromConfig('annual')['name'] - ); - - $this->assertEquals( - 'annual', - InstanceHelper::getPlanInformationFromConfig('annual')['id'] - ); - - $this->assertEquals( - 1000, - InstanceHelper::getPlanInformationFromConfig('annual')['price'] - ); - - $this->assertEquals( - '$10.00', - InstanceHelper::getPlanInformationFromConfig('annual')['friendlyPrice'] - ); - } - /** @test */ public function it_gets_latest_changelog_entries() { From 773b85312b962160c60ebb18ef32e121c0c5b61b Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Thu, 25 Aug 2022 07:25:57 -0400 Subject: [PATCH 33/41] Delete AccountSubscriptionTest.php --- tests/Feature/AccountSubscriptionTest.php | 38 ----------------------- 1 file changed, 38 deletions(-) delete mode 100644 tests/Feature/AccountSubscriptionTest.php diff --git a/tests/Feature/AccountSubscriptionTest.php b/tests/Feature/AccountSubscriptionTest.php deleted file mode 100644 index 3c243ab0b14..00000000000 --- a/tests/Feature/AccountSubscriptionTest.php +++ /dev/null @@ -1,38 +0,0 @@ -signin(); - - $response = $this->get('/settings/subscriptions'); - - $response->assertSee('Pick a plan below and join over 0 persons who upgraded their Monica.'); - } - - public function test_it_get_subscription_page() - { - $user = $this->signin(); - - $response = $this->get('/settings/subscriptions'); - - $response->assertSee('You are on the Annual plan. Thanks so much for being a subscriber.'); - } - - public function test_it_get_blank_page_on_update_if_not_subscribed() - { - $this->signin(); - - $response = $this->get('/settings/subscriptions/update'); - - $response->assertSee('Upgrade Monica today and have more meaningful relationships.'); - } -} From 754222280d6aa27947e31e5a7c64bf7bd6bd488e Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sun, 2 Oct 2022 09:04:10 -0400 Subject: [PATCH 34/41] fixes --- .../Settings/SubscriptionsController.php | 12 ++-- app/Models/Account/Account.php | 2 + config/monica.php | 2 + ...08_115818_add_licence_keys_to_accounts.php | 5 ++ .../settings/subscriptions/blank.blade.php | 9 ++- .../settings/subscriptions/stripe.blade.php | 60 +++++++++++++++++++ 6 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 resources/views/settings/subscriptions/stripe.blade.php diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index e86d8274d95..c30543d79fe 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -15,11 +15,6 @@ class SubscriptionsController extends Controller { - /** - * Display a listing of the resource. - * - * @return View|Factory|RedirectResponse - */ public function index() { if (! config('monica.requires_subscription')) { @@ -28,6 +23,13 @@ public function index() $account = auth()->user()->account; + if ($account->is_on_stripe) { + return view('settings.subscriptions.stripe', [ + 'customerPortalUrl' => config('monica.customer_portal_stripe_url'), + 'accountHasLimitations' => AccountHelper::hasLimitations($account), + ]); + } + if (! $account->isSubscribed()) { return view('settings.subscriptions.blank', [ 'customerPortalUrl' => config('monica.customer_portal_url'), diff --git a/app/Models/Account/Account.php b/app/Models/Account/Account.php index 43de840f3f0..c58643dacb8 100644 --- a/app/Models/Account/Account.php +++ b/app/Models/Account/Account.php @@ -76,6 +76,7 @@ class Account extends Model 'licence_key', 'valid_until_at', 'purchaser_email', + 'is_on_stripe', ]; /** @@ -85,6 +86,7 @@ class Account extends Model */ protected $casts = [ 'has_access_to_paid_version_for_free' => 'boolean', + 'is_on_stripe' => 'boolean', ]; /** diff --git a/config/monica.php b/config/monica.php index 5064acf84e7..da5067f2a72 100644 --- a/config/monica.php +++ b/config/monica.php @@ -300,6 +300,8 @@ 'customer_portal_client_secret' => env('CUSTOMER_PORTAL_CLIENT_SECRET'), + 'customer_portal_stripe_url' => env('CUSTOMER_PORTAL_STRIPE_URL', ''), + /* |-------------------------------------------------------------------------- | Licence key encryption key diff --git a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php index 349e67a3032..4c70be2656f 100644 --- a/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php +++ b/database/migrations/2022_03_08_115818_add_licence_keys_to_accounts.php @@ -1,5 +1,6 @@ datetime('valid_until_at')->after('licence_key')->nullable(); $table->string('purchaser_email', 255)->after('valid_until_at')->nullable(); $table->string('frequency', 15)->after('purchaser_email')->nullable(); + $table->boolean('is_on_stripe')->after('frequency')->default(false); }); + + Account::whereNotNull('stripe_id')->update(['is_on_stripe' => true]); } /** @@ -33,6 +37,7 @@ public function down() $table->dropColumn('valid_until_at'); $table->dropColumn('purchaser_email'); $table->dropColumn('frequency'); + $table->dropColumn('is_on_stripe'); }); } } diff --git a/resources/views/settings/subscriptions/blank.blade.php b/resources/views/settings/subscriptions/blank.blade.php index fa8bd98754a..3e302a4909a 100644 --- a/resources/views/settings/subscriptions/blank.blade.php +++ b/resources/views/settings/subscriptions/blank.blade.php @@ -36,7 +36,6 @@
    -

    {{ trans('settings.subscriptions_account_payment') }}

    @@ -101,7 +100,11 @@
    -

    {{ trans('settings.subscriptions_plan_question') }}

    +

    Steps to have a subscription

    + +

    1. Go to the customer portal to get a licence key

    +

    2. Subscribe and obtain your licence key

    +

    3. Paste your licence key below.

    @include('partials.errors') @@ -109,7 +112,7 @@ @csrf
    - +
    diff --git a/resources/views/settings/subscriptions/stripe.blade.php b/resources/views/settings/subscriptions/stripe.blade.php new file mode 100644 index 00000000000..85195f23874 --- /dev/null +++ b/resources/views/settings/subscriptions/stripe.blade.php @@ -0,0 +1,60 @@ +@extends('layouts.skeleton') + +@section('content') + +
    + + {{-- Breadcrumb --}} + + +
    +
    + + @include('settings._sidebar') + +
    + +
    +
    + +

    {{ trans('settings.subscriptions_account_current_plan') }}

    + +

    Thanks for being a subscriber.

    +

    You can edit/cancel your plan or update your credit card information below.

    + +

    You will need to login using the email address you've used at the time you've subscried to Monica. Once you enter your email address, you will receive a unique code to your email address to confirm your identity. From there, you'll be able to manage your subscriptions.

    + +

    + + Manage your subscription + +

    + +

    Reminder: everything billing related is handled by Stripe, and we have no access to the credit card information at all.

    +
    +
    + +
    +
    +
    +
    + +@endsection From 30d9f9991253bae3a9e1bec0762acb4208b6061f Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sun, 2 Oct 2022 13:05:09 +0000 Subject: [PATCH 35/41] Apply fixes from StyleCI --- app/Http/Controllers/Settings/SubscriptionsController.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/Http/Controllers/Settings/SubscriptionsController.php b/app/Http/Controllers/Settings/SubscriptionsController.php index c30543d79fe..b3413f9142f 100644 --- a/app/Http/Controllers/Settings/SubscriptionsController.php +++ b/app/Http/Controllers/Settings/SubscriptionsController.php @@ -3,13 +3,10 @@ namespace App\Http\Controllers\Settings; use Exception; -use Illuminate\View\View; use App\Helpers\DateHelper; use Illuminate\Http\Request; use App\Helpers\AccountHelper; use App\Http\Controllers\Controller; -use Illuminate\Http\RedirectResponse; -use Illuminate\Contracts\View\Factory; use Illuminate\Validation\ValidationException; use App\Services\Account\Subscription\ActivateLicenceKey; From fa6b646584ae6ea1f80f0671335c470a65ae054d Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sun, 2 Oct 2022 09:35:05 -0400 Subject: [PATCH 36/41] fix --- phpstan.neon | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index b3314a83142..a44e800edd2 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -34,8 +34,6 @@ parameters: path: */Traits/Searchable.php - message: '#Access to an undefined property Faker\\Generator::\$state\.#' path: */Console/Commands/SetupTest.php - - message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::recurring\(\)\.#' - path: */Traits/Subscription.php - message: '#Function dns_get_record is unsafe to use\. It can return FALSE instead of throwing an exception\. Please add ''use function Safe\\dns_get_record;'' at the beginning of the file to use the variant provided by the ''thecodingmachine/safe'' library\.#' path: */Services/DavClient/Utils/Dav/ServiceUrlQuery.php - message: '#Access to an undefined property App\\Models\\Relationship\\Relationship::\$relationshipTypeLocalized\.#' From 258c427af0cfb0473c672bd76746f7934650f21f Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Tue, 18 Oct 2022 21:32:26 +0200 Subject: [PATCH 37/41] use MissingPrivateKeyException --- .../NoLicenceKeyEncryptionSetException.php | 19 ------------------- .../Subscription/ActivateLicenceKey.php | 4 ++-- .../Subscription/ActivateLicenceKeyTest.php | 4 ++-- 3 files changed, 4 insertions(+), 23 deletions(-) delete mode 100644 app/Exceptions/NoLicenceKeyEncryptionSetException.php diff --git a/app/Exceptions/NoLicenceKeyEncryptionSetException.php b/app/Exceptions/NoLicenceKeyEncryptionSetException.php deleted file mode 100644 index 1eb7d234a48..00000000000 --- a/app/Exceptions/NoLicenceKeyEncryptionSetException.php +++ /dev/null @@ -1,19 +0,0 @@ - null]); - $this->expectException(NoLicenceKeyEncryptionSetException::class); + $this->expectException(MissingPrivateKeyException::class); $account = factory(Account::class)->create([]); From 9db197547602102fd54fc2a9eb92ec9fcb793a3b Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 18 Oct 2022 19:32:49 +0000 Subject: [PATCH 38/41] Apply fixes from StyleCI --- app/Services/Account/Subscription/ActivateLicenceKey.php | 2 +- .../Services/Account/Subscription/ActivateLicenceKeyTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index 863c3186dd3..d3f09894889 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -8,8 +8,8 @@ use App\Services\DispatchableService; use App\Exceptions\LicenceKeyErrorException; use App\Exceptions\LicenceKeyInvalidException; -use App\Exceptions\LicenceKeyDontExistException; use App\Exceptions\MissingPrivateKeyException; +use App\Exceptions\LicenceKeyDontExistException; class ActivateLicenceKey extends BaseService implements QueuableService { diff --git a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php index ef44e9b02ec..13b2173e04f 100644 --- a/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php +++ b/tests/Unit/Services/Account/Subscription/ActivateLicenceKeyTest.php @@ -7,9 +7,9 @@ use App\Models\Account\Account; use App\Exceptions\LicenceKeyErrorException; use App\Exceptions\LicenceKeyInvalidException; +use App\Exceptions\MissingPrivateKeyException; use Illuminate\Validation\ValidationException; use App\Exceptions\LicenceKeyDontExistException; -use App\Exceptions\MissingPrivateKeyException; use Illuminate\Foundation\Testing\DatabaseTransactions; use App\Services\Account\Subscription\ActivateLicenceKey; use App\Services\Account\Subscription\CustomerPortalCall; From 9884708682f425eb3267449256b0232aee05e858 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Wed, 19 Oct 2022 11:10:42 +0200 Subject: [PATCH 39/41] get next_check_at from api call --- .../Subscription/ActivateLicenceKey.php | 19 ++++++++++++++++--- .../Subscription/CustomerPortalCall.php | 9 ++++++--- .../Subscription/CustomerPortalCallTest.php | 7 ++++--- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/app/Services/Account/Subscription/ActivateLicenceKey.php b/app/Services/Account/Subscription/ActivateLicenceKey.php index d3f09894889..c4b7dacdf34 100644 --- a/app/Services/Account/Subscription/ActivateLicenceKey.php +++ b/app/Services/Account/Subscription/ActivateLicenceKey.php @@ -18,6 +18,7 @@ class ActivateLicenceKey extends BaseService implements QueuableService private Account $account; private array $data; private int $status; + private array $response; /** * Get the validation rules that apply to the service. @@ -60,9 +61,11 @@ private function validateEnvVariables(): void private function makeRequestToCustomerPortal(): void { - $this->status = app(CustomerPortalCall::class)->execute([ + $data = app(CustomerPortalCall::class)->execute([ 'licence_key' => $this->data['licence_key'], ]); + $this->status = $data['status']; + $this->response = $data['data']; } private function checkResponseCode(): void @@ -85,9 +88,19 @@ private function store(): void $licenceKey = $this->decodeKey(); $this->account->licence_key = $this->data['licence_key']; - $this->account->valid_until_at = $licenceKey['next_check_at']; + $this->account->valid_until_at = $this->response['next_check_at']; $this->account->purchaser_email = $licenceKey['purchaser_email']; - $this->account->frequency = $licenceKey['frequency']; + switch ($licenceKey['frequency']) { + case 'month': + $this->account->frequency = 'monthly'; + break; + case 'year': + $this->account->frequency = 'annual'; + break; + default: + $this->account->frequency = $licenceKey['frequency']; + break; + } $this->account->save(); } diff --git a/app/Services/Account/Subscription/CustomerPortalCall.php b/app/Services/Account/Subscription/CustomerPortalCall.php index a52a144493b..ec898f9eda4 100644 --- a/app/Services/Account/Subscription/CustomerPortalCall.php +++ b/app/Services/Account/Subscription/CustomerPortalCall.php @@ -31,9 +31,9 @@ public function rules() * If it is, activate the licence key and set the valid_until_at date. * * @param array $data - * @return int + * @return array */ - public function execute(array $data): int + public function execute(array $data): array { $this->validate($data); $this->data = $data; @@ -43,7 +43,10 @@ public function execute(array $data): int $accessToken = $this->getAccessToken(); $response = $this->makeRequestToCustomerPortal($accessToken); - return $response->status(); + return [ + 'status' => $response->status(), + 'data' => $response->json(), + ]; } private function validateEnvVariables(): void diff --git a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php index 934d55e17d4..7a0478a2c2d 100644 --- a/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php +++ b/tests/Unit/Services/Account/Subscription/CustomerPortalCallTest.php @@ -27,16 +27,17 @@ public function it_validates_a_licence_key() Http::fake([ 'https://fake.test/oauth/token' => Http::response(['access_token' => '123']), - 'https://fake.test/api/validate' => Http::response([], 200), + 'https://fake.test/api/validate' => Http::response(['data' => 'ok'], 200), ]); $request = [ 'licence_key' => 'key', ]; - $status = app(CustomerPortalCall::class)->execute($request); + $response = app(CustomerPortalCall::class)->execute($request); - $this->assertEquals(200, $status); + $this->assertEquals(200, $response['status']); + $this->assertEquals(['data' => 'ok'], $response['data']); Http::assertSentInOrder([ function ($request, $response) { From c6ac38e5cfde3c1aefd5b6d099d96eda31075fe4 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Fri, 21 Oct 2022 00:14:38 +0200 Subject: [PATCH 40/41] fix job schedule --- app/Console/Kernel.php | 28 ++++++++++++++++++++++++---- app/Console/Scheduling/CronEvent.php | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index a38694523de..9b8229a975c 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -56,7 +56,7 @@ protected function schedule(Schedule $schedule) } $this->scheduleCommand($schedule, 'model:prune', 'daily'); - $schedule->job(new CheckLicenceKeys)->everySixHours(); + $this->scheduleJob($schedule, CheckLicenceKeys::class, 'minutes', 60 * 6); } /** @@ -64,12 +64,32 @@ protected function schedule(Schedule $schedule) * * @codeCoverageIgnore */ - private function scheduleCommand(Schedule $schedule, string $command, $frequency) + private function scheduleCommand(Schedule $schedule, string $command, string $frequency, mixed ...$params) { - $schedule->command($command)->when(function () use ($command, $frequency) { + $this->scheduleAction($schedule, $command, $frequency, $params); + } + + /** + * Define a new schedule command with a frequency. + * + * @codeCoverageIgnore + */ + private function scheduleJob(Schedule $schedule, string $job, string $frequency, mixed ...$params) + { + $this->scheduleAction($schedule, $job, $frequency, $params, 'job'); + } + + /** + * Define a new schedule. + * + * @codeCoverageIgnore + */ + private function scheduleAction(Schedule $schedule, string $command, string $frequency, array $params, string $action = 'command') + { + $schedule->$action($command)->when(function () use ($command, $frequency, $params) { $event = CronEvent::command($command); if ($frequency) { - $event = $event->$frequency(); + $event = $event->{$frequency}(...$params); } return $event->isDue(); diff --git a/app/Console/Scheduling/CronEvent.php b/app/Console/Scheduling/CronEvent.php index 3245c7705ce..0fca6639113 100644 --- a/app/Console/Scheduling/CronEvent.php +++ b/app/Console/Scheduling/CronEvent.php @@ -96,6 +96,20 @@ public function weekly(): self return $this; } + /** + * Run the command every $minutes. + * + * @param int $minutes + * @return self + */ + public function minutes(int $minutes): self + { + $this->minutes = $minutes; + $this->days = 0; + + return $this; + } + /** * Test if the command is due to run. * From 25a191690e7627948a34f7c6e700731273ee2eec Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Fri, 21 Oct 2022 00:14:52 +0200 Subject: [PATCH 41/41] update change and cancel links --- resources/views/settings/subscriptions/account.blade.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/views/settings/subscriptions/account.blade.php b/resources/views/settings/subscriptions/account.blade.php index 41ccb5662ce..70a94df5edf 100644 --- a/resources/views/settings/subscriptions/account.blade.php +++ b/resources/views/settings/subscriptions/account.blade.php @@ -55,7 +55,9 @@
    @@ -73,7 +75,7 @@