diff --git a/composer.json b/composer.json index 31004750..65b74c05 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "jaybizzle/laravel-crawler-detect": "^1.2", "kyslik/column-sortable": "^6.4.1", "laravel/fortify": "^1.8.3", - "laravel/framework": "^8.69.0", + "laravel/framework": "^8.77.1", "laravel/sanctum": "^2.12.1", "laravel/tinker": "^2.6.2", "laravel/ui": "^3.3.1", diff --git a/composer.lock b/composer.lock index e905542c..4ea12224 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": "f7357a3aa76857d61639d3e8eeaa9178", + "content-hash": "2a61d9183cbd4714a8736cec2589a3ae", "packages": [ { "name": "amphp/amp", @@ -174,22 +174,22 @@ }, { "name": "asm89/stack-cors", - "version": "v2.0.3", + "version": "v2.0.5", "source": { "type": "git", "url": "https://github.com/asm89/stack-cors.git", - "reference": "9cb795bf30988e8c96dd3c40623c48a877bc6714" + "reference": "7a198ec737e926eab15d29368fc6fff66772b0e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/asm89/stack-cors/zipball/9cb795bf30988e8c96dd3c40623c48a877bc6714", - "reference": "9cb795bf30988e8c96dd3c40623c48a877bc6714", + "url": "https://api.github.com/repos/asm89/stack-cors/zipball/7a198ec737e926eab15d29368fc6fff66772b0e2", + "reference": "7a198ec737e926eab15d29368fc6fff66772b0e2", "shasum": "" }, "require": { "php": "^7.0|^8.0", - "symfony/http-foundation": "~2.7|~3.0|~4.0|~5.0", - "symfony/http-kernel": "~2.7|~3.0|~4.0|~5.0" + "symfony/http-foundation": "~2.7|~3.0|~4.0|~5.0|~6.0", + "symfony/http-kernel": "~2.7|~3.0|~4.0|~5.0|~6.0" }, "require-dev": { "phpunit/phpunit": "^6|^7|^8|^9", @@ -224,9 +224,9 @@ ], "support": { "issues": "https://github.com/asm89/stack-cors/issues", - "source": "https://github.com/asm89/stack-cors/tree/v2.0.3" + "source": "https://github.com/asm89/stack-cors/tree/v2.0.5" }, - "time": "2021-03-11T06:42:03+00:00" + "time": "2022-01-03T15:27:13+00:00" }, { "name": "aws/aws-crt-php", @@ -280,16 +280,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.208.7", + "version": "3.208.8", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "41a800dd7cf5c4ac0ef9bf8db01e838ab6a3698c" + "reference": "1fe99375c5a9012d8f99dbbe59fff8e7131a9703" }, "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/1fe99375c5a9012d8f99dbbe59fff8e7131a9703", + "reference": "1fe99375c5a9012d8f99dbbe59fff8e7131a9703", "shasum": "" }, "require": { @@ -365,9 +365,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.208.8" }, - "time": "2021-12-21T19:16:39+00:00" + "time": "2022-01-03T19:22:28+00:00" }, { "name": "bacon/bacon-qr-code", @@ -2137,16 +2137,16 @@ }, { "name": "fruitcake/laravel-cors", - "version": "v2.0.4", + "version": "v2.0.5", "source": { "type": "git", "url": "https://github.com/fruitcake/laravel-cors.git", - "reference": "a8ccedc7ca95189ead0e407c43b530dc17791d6a" + "reference": "3a066e5cac32e2d1cdaacd6b961692778f37b5fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/a8ccedc7ca95189ead0e407c43b530dc17791d6a", - "reference": "a8ccedc7ca95189ead0e407c43b530dc17791d6a", + "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/3a066e5cac32e2d1cdaacd6b961692778f37b5fc", + "reference": "3a066e5cac32e2d1cdaacd6b961692778f37b5fc", "shasum": "" }, "require": { @@ -2154,11 +2154,11 @@ "illuminate/contracts": "^6|^7|^8|^9", "illuminate/support": "^6|^7|^8|^9", "php": ">=7.2", - "symfony/http-foundation": "^4|^5", - "symfony/http-kernel": "^4.3.4|^5" + "symfony/http-foundation": "^4|^5|^6", + "symfony/http-kernel": "^4.3.4|^5|^6" }, "require-dev": { - "laravel/framework": "^6|^7|^8", + "laravel/framework": "^6|^7.24|^8", "orchestra/testbench-dusk": "^4|^5|^6|^7", "phpunit/phpunit": "^6|^7|^8|^9", "squizlabs/php_codesniffer": "^3.5" @@ -2202,15 +2202,19 @@ ], "support": { "issues": "https://github.com/fruitcake/laravel-cors/issues", - "source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.4" + "source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.5" }, "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, { "url": "https://github.com/barryvdh", "type": "github" } ], - "time": "2021-04-26T11:24:25+00:00" + "time": "2022-01-03T14:53:04+00:00" }, { "name": "gabrielelana/byte-units", @@ -3479,16 +3483,16 @@ }, { "name": "league/commonmark", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "819276bc54e83c160617d3ac0a436c239e479928" + "reference": "17d2b9cb5161a2ea1a8dd30e6991d668e503fb9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/819276bc54e83c160617d3ac0a436c239e479928", - "reference": "819276bc54e83c160617d3ac0a436c239e479928", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/17d2b9cb5161a2ea1a8dd30e6991d668e503fb9d", + "reference": "17d2b9cb5161a2ea1a8dd30e6991d668e503fb9d", "shasum": "" }, "require": { @@ -3578,7 +3582,7 @@ "type": "tidelift" } ], - "time": "2021-12-05T18:25:20+00:00" + "time": "2022-01-02T18:25:06+00:00" }, { "name": "league/config", @@ -3991,7 +3995,7 @@ "dist": { "type": "path", "url": "../../PhpstormProjects/subscription", - "reference": "236701da1048382c442d7cc85af7acf1d7143a5d" + "reference": "7da5a827d93fb3eea2da4fad64facf79aab2b40e" }, "require": { "friendsofphp/php-cs-fixer": "^3.3.2", @@ -10935,16 +10939,16 @@ }, { "name": "vimeo/psalm", - "version": "4.16.1", + "version": "4.17.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "aa7e400908833b10c0333861f86cd48c510b60eb" + "reference": "6f4707aa41c9174353a6434bba3fc8840f981d9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/aa7e400908833b10c0333861f86cd48c510b60eb", - "reference": "aa7e400908833b10c0333861f86cd48c510b60eb", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/6f4707aa41c9174353a6434bba3fc8840f981d9c", + "reference": "6f4707aa41c9174353a6434bba3fc8840f981d9c", "shasum": "" }, "require": { @@ -10952,7 +10956,7 @@ "amphp/byte-stream": "^1.5", "composer/package-versions-deprecated": "^1.8.0", "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0", + "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", "dnoegel/php-xdg-base-dir": "^0.1.1", "ext-ctype": "*", "ext-dom": "*", @@ -11035,9 +11039,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.16.1" + "source": "https://github.com/vimeo/psalm/tree/4.17.0" }, - "time": "2021-12-26T08:17:05+00:00" + "time": "2022-01-01T18:39:47+00:00" }, { "name": "vlucas/phpdotenv", diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index de9dcb8f..d7440df7 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -1,4 +1,5 @@ Str::uuid(), 'role' => $this->faker->randomElement( ['user', 'admin'] ), @@ -44,16 +46,16 @@ class UserFactory extends Factory $user ->settings() ->create([ - 'name' => $this->faker->name, - 'address' => $this->faker->address, - 'state' => $this->faker->state, - 'city' => $this->faker->city, - 'postal_code' => $this->faker->postcode, - 'country' => $this->faker->randomElement( + 'name' => $this->faker->name, + 'address' => $this->faker->address, + 'state' => $this->faker->state, + 'city' => $this->faker->city, + 'postal_code' => $this->faker->postcode, + 'country' => $this->faker->randomElement( ['SK', 'CZ', 'DE', 'FR'] ), - 'phone_number' => $this->faker->phoneNumber, - 'timezone' => $this->faker->randomElement( + 'phone_number' => $this->faker->phoneNumber, + 'timezone' => $this->faker->randomElement( ['+1.0', '+2.0', '+3.0'] ), ]); diff --git a/src/App/Console/Commands/SetupDevEnvironment.php b/src/App/Console/Commands/SetupDevEnvironment.php index 2ff55bee..d3fe6065 100644 --- a/src/App/Console/Commands/SetupDevEnvironment.php +++ b/src/App/Console/Commands/SetupDevEnvironment.php @@ -202,7 +202,7 @@ class SetupDevEnvironment extends Command 'created_at' => now(), ]); - Share::factory(Share::class) + Share::factory() ->create([ 'type' => 'folder', 'item_id' => $shared_folder->id, @@ -337,7 +337,7 @@ class SetupDevEnvironment extends Command 'created_at' => now()->subMinutes(4), ]); - Share::factory(Share::class) + Share::factory() ->create([ 'type' => 'folder', 'item_id' => $documents->id, diff --git a/src/App/Limitations/Engines/DefaultLimitationEngine.php b/src/App/Limitations/Engines/DefaultLimitationEngine.php new file mode 100644 index 00000000..98f1444e --- /dev/null +++ b/src/App/Limitations/Engines/DefaultLimitationEngine.php @@ -0,0 +1,36 @@ +usedCapacity + $fileSize, + maxAmount: $user->limitations->max_storage_amount, + ); + + // 2. Check if storage usage exceed predefined capacity + return ! ($usedPercentage >= 100) + ; + } + + public function canDownload(User $user): bool + { + return true; + } + + public function canCreateFolder(User $user): bool + { + return true; + } +} diff --git a/src/App/Limitations/Engines/FixedBillingLimitationEngine.php b/src/App/Limitations/Engines/FixedBillingLimitationEngine.php new file mode 100644 index 00000000..694250b6 --- /dev/null +++ b/src/App/Limitations/Engines/FixedBillingLimitationEngine.php @@ -0,0 +1,31 @@ +usedCapacity + $fileSize, + maxAmount: $user->limitations->max_storage_amount, + ); + + // Check if storage usage exceed predefined capacity + return ! ($usedPercentage >= 100) + ; + } + + public function canDownload(User $user): bool + { + return true; + } + + public function canCreateFolder(User $user): bool + { + return true; + } +} diff --git a/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php b/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php new file mode 100644 index 00000000..5a0c1142 --- /dev/null +++ b/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php @@ -0,0 +1,29 @@ +failedPayments()->count() >= 3) + ; + } + + public function canDownload(User $user): bool + { + // Disable upload when user has more than 3 failed payments + return ! ($user->failedPayments()->count() >= 3) + ; + } + + public function canCreateFolder(User $user): bool + { + // Disable upload when user has more than 3 failed payments + return ! ($user->failedPayments()->count() >= 3) + ; + } +} diff --git a/src/App/Limitations/LimitationEngine.php b/src/App/Limitations/LimitationEngine.php new file mode 100644 index 00000000..a118c5ff --- /dev/null +++ b/src/App/Limitations/LimitationEngine.php @@ -0,0 +1,13 @@ += 100) { - // Delete file - Storage::disk('local') - ->delete("chunks/$temp_filename"); - - // Abort uploading - abort(423, 'You exceed your storage limit!'); - } - } -} diff --git a/src/App/Users/Actions/FormatUsageEstimatesAction.php b/src/App/Users/Actions/FormatUsageEstimatesAction.php index f01c5b7b..0bfcab6c 100644 --- a/src/App/Users/Actions/FormatUsageEstimatesAction.php +++ b/src/App/Users/Actions/FormatUsageEstimatesAction.php @@ -1,5 +1,4 @@ Metric::megabytes($estimate['usage'])->format(), 'flatFee' => intval($estimate['usage']) . ' ' . __('Pcs.'), - 'member' => intval($estimate['usage']) . ' ' . __('Mem.'), + 'member' => intval($estimate['usage']) . ' ' . __('Mem.'), }; // Normalize units @@ -29,7 +28,7 @@ class FormatUsageEstimatesAction 'amount' => $amount, 'cost' => format_currency($amount, $currency), 'usage' => $usage, - ] + ], ]; }); } diff --git a/src/App/Users/Models/User.php b/src/App/Users/Models/User.php index 1bd9c440..61cebcac 100644 --- a/src/App/Users/Models/User.php +++ b/src/App/Users/Models/User.php @@ -12,6 +12,7 @@ use Illuminate\Support\Facades\DB; use Database\Factories\UserFactory; use Domain\Settings\Models\Setting; use Kyslik\ColumnSortable\Sortable; +use App\Limitations\LimitationManager; use Illuminate\Support\Facades\Storage; use Illuminate\Notifications\Notifiable; use App\Users\Notifications\ResetPassword; @@ -87,6 +88,17 @@ class User extends Authenticatable implements MustVerifyEmail return UserFactory::new(); } + public function __call($method, $parameters) + { + if (str_starts_with($method, 'can')) { + return resolve(LimitationManager::class) + ->driver() + ->$method($this, ...$parameters); + } + + return parent::__call($method, $parameters); + } + /** * Get user used storage details */ @@ -102,8 +114,8 @@ class User extends Authenticatable implements MustVerifyEmail } return [ - 'used' => (float) get_storage_fill_percentage($this->usedCapacity, $this->limitations->max_storage_amount), - 'used_formatted' => get_storage_fill_percentage($this->usedCapacity, $this->limitations->max_storage_amount) . '%', + 'used' => (float) get_storage_percentage($this->usedCapacity, $this->limitations->max_storage_amount), + 'used_formatted' => get_storage_percentage($this->usedCapacity, $this->limitations->max_storage_amount) . '%', 'capacity' => $this->limitations->max_storage_amount, 'capacity_formatted' => format_gigabytes($this->limitations->max_storage_amount), ]; diff --git a/src/App/Users/Models/UserLimitation.php b/src/App/Users/Models/UserLimitation.php index cc700024..290c96ec 100644 --- a/src/App/Users/Models/UserLimitation.php +++ b/src/App/Users/Models/UserLimitation.php @@ -60,7 +60,7 @@ class UserLimitation extends Model return [ 'use' => Metric::bytes($userCapacity)->format(), 'total' => format_gigabytes($this->max_storage_amount), - 'percentage' => get_storage_fill_percentage($userCapacity, $this->max_storage_amount), + 'percentage' => get_storage_percentage($userCapacity, $this->max_storage_amount), ]; } diff --git a/src/App/Users/Resources/UserResource.php b/src/App/Users/Resources/UserResource.php index 9161916a..1e3c94f6 100644 --- a/src/App/Users/Resources/UserResource.php +++ b/src/App/Users/Resources/UserResource.php @@ -4,12 +4,12 @@ namespace App\Users\Resources; use Domain\Folders\Resources\FolderCollection; use Illuminate\Http\Resources\Json\JsonResource; use App\Users\Actions\FormatUsageEstimatesAction; -use VueFileManager\Subscription\Domain\CreditCards\Resources\CreditCardCollection; use VueFileManager\Subscription\Domain\Credits\Resources\BalanceResource; +use VueFileManager\Subscription\Domain\CreditCards\Resources\CreditCardCollection; use VueFileManager\Subscription\Domain\BillingAlerts\Resources\BillingAlertResource; -use VueFileManager\Subscription\Domain\FailedPayments\Resources\FailedPaymentsCollection; use VueFileManager\Subscription\Domain\Subscriptions\Resources\SubscriptionResource; use VueFileManager\Subscription\Domain\Usage\Actions\SumUsageForCurrentPeriodAction; +use VueFileManager\Subscription\Domain\FailedPayments\Resources\FailedPaymentsCollection; class UserResource extends JsonResource { @@ -41,8 +41,8 @@ class UserResource extends JsonResource 'updated_at' => format_date($this->updated_at, '%d. %B. %Y'), ], 'relationships' => [ - 'settings' => new SettingsResource($this->settings), - 'favourites' => new FolderCollection($this->favouriteFolders), + 'settings' => new SettingsResource($this->settings), + 'favourites' => new FolderCollection($this->favouriteFolders), 'creditCards' => new CreditCardCollection($this->creditCards), $this->mergeWhen($this->hasSubscription(), fn () => [ 'subscription' => new SubscriptionResource($this->subscription), diff --git a/src/App/Users/Resources/UserStorageResource.php b/src/App/Users/Resources/UserStorageResource.php index 4cfcf889..959dea1e 100644 --- a/src/App/Users/Resources/UserStorageResource.php +++ b/src/App/Users/Resources/UserStorageResource.php @@ -31,7 +31,7 @@ class UserStorageResource extends JsonResource 'attributes' => [ 'used' => Metric::bytes($this->usedCapacity)->format(), 'capacity' => format_gigabytes($totalCapacity), - 'percentage' => (float) get_storage_fill_percentage($this->usedCapacity, $totalCapacity), + 'percentage' => (float) get_storage_percentage($this->usedCapacity, $totalCapacity), ], 'meta' => [ 'traffic' => [ @@ -44,23 +44,23 @@ class UserStorageResource extends JsonResource ], 'images' => [ 'used' => Metric::bytes($images)->format(), - 'percentage' => (float) get_storage_fill_percentage($images, $totalCapacity), + 'percentage' => (float) get_storage_percentage($images, $totalCapacity), ], 'audios' => [ 'used' => Metric::bytes($audios)->format(), - 'percentage' => (float) get_storage_fill_percentage($audios, $totalCapacity), + 'percentage' => (float) get_storage_percentage($audios, $totalCapacity), ], 'videos' => [ 'used' => Metric::bytes($videos)->format(), - 'percentage' => (float) get_storage_fill_percentage($videos, $totalCapacity), + 'percentage' => (float) get_storage_percentage($videos, $totalCapacity), ], 'documents' => [ 'used' => Metric::bytes($documents)->format(), - 'percentage' => (float) get_storage_fill_percentage($documents, $totalCapacity), + 'percentage' => (float) get_storage_percentage($documents, $totalCapacity), ], 'others' => [ 'used' => Metric::bytes($others)->format(), - 'percentage' => (float) get_storage_fill_percentage($others, $totalCapacity), + 'percentage' => (float) get_storage_percentage($others, $totalCapacity), ], ], ], diff --git a/src/Domain/Files/Actions/ProcessImageThumbnailAction.php b/src/Domain/Files/Actions/ProcessImageThumbnailAction.php index 0f687697..dc382fb4 100644 --- a/src/Domain/Files/Actions/ProcessImageThumbnailAction.php +++ b/src/Domain/Files/Actions/ProcessImageThumbnailAction.php @@ -7,7 +7,8 @@ class ProcessImageThumbnailAction { public function __construct( public GenerateImageThumbnailAction $generateImageThumbnail, - ) {} + ) { + } private array $availableFormats = [ 'image/gif', diff --git a/src/Domain/Files/Actions/UploadFileAction.php b/src/Domain/Files/Actions/UploadFileAction.php index 5fcc55af..32774bad 100644 --- a/src/Domain/Files/Actions/UploadFileAction.php +++ b/src/Domain/Files/Actions/UploadFileAction.php @@ -9,16 +9,15 @@ use Illuminate\Support\Facades\Storage; use Domain\Files\Requests\UploadRequest; use Domain\Files\Models\File as UserFile; use Domain\Traffic\Actions\RecordUploadAction; -use App\Users\Actions\CheckStorageCapacityAction; class UploadFileAction { public function __construct( public RecordUploadAction $recordUpload, - public CheckStorageCapacityAction $checkStorageCapacity, public ProcessImageThumbnailAction $createImageThumbnail, public MoveFileToExternalStorageAction $moveFileToExternalStorage, - ) {} + ) { + } /** * Upload new file @@ -58,7 +57,7 @@ class UploadFileAction $disk_local = Storage::disk('local'); // Get user data - $user_id = $shared->user_id ?? Auth::id(); + $user = $shared->user ?? Auth::user(); // File Info $fileSize = $disk_local->size("chunks/$chunkName"); @@ -66,21 +65,25 @@ class UploadFileAction $file_mimetype = $disk_local->mimeType("chunks/$chunkName"); // Check if user has enough space to upload file - ($this->checkStorageCapacity)($user_id, $fileSize, $chunkName); + if (! $user->canUpload($fileSize)) { + Storage::disk('local')->delete("chunks/$chunkName"); + + abort(423, 'You exceed your storage limit!'); + } // Move finished file from chunk to file-manager directory - $disk_local->move("chunks/$chunkName", "files/$user_id/$fileName"); + $disk_local->move("chunks/$chunkName", "files/$user->id/$fileName"); // Create multiple image thumbnails - ($this->createImageThumbnail)($fileName, $file, $user_id); + ($this->createImageThumbnail)($fileName, $file, $user->id); // Move files to external storage if (! is_storage_driver('local')) { - ($this->moveFileToExternalStorage)($fileName, $user_id); + ($this->moveFileToExternalStorage)($fileName, $user->id); } // Store user upload size - ($this->recordUpload)($fileSize, $user_id); + ($this->recordUpload)($fileSize, $user->id); // Return new file return UserFile::create([ @@ -92,7 +95,7 @@ class UploadFileAction 'basename' => $fileName, 'author' => $shared ? 'visitor' : 'user', 'filesize' => $fileSize, - 'user_id' => $user_id, + 'user_id' => $user->id, ]); } } diff --git a/src/Domain/Files/Resources/FileResource.php b/src/Domain/Files/Resources/FileResource.php index 6dd56cdf..c89a66c3 100644 --- a/src/Domain/Files/Resources/FileResource.php +++ b/src/Domain/Files/Resources/FileResource.php @@ -35,7 +35,7 @@ class FileResource extends JsonResource 'parent_id' => $this->parent_id, 'updated_at' => $this->updated_at, 'created_at' => Carbon::parse($this->created_at)->diffForHumans(), - 'deleted_at' => Carbon::parse($this->deleted_at)->diffForHumans(), + 'deleted_at' => $this->deleted_at ? Carbon::parse($this->deleted_at)->diffForHumans() : null, /*'updated_at' => format_date( set_time_by_user_timezone($this->updated_at), __t('time') ), diff --git a/src/Domain/Folders/Resources/FolderResource.php b/src/Domain/Folders/Resources/FolderResource.php index d3cf9726..f7bacc90 100644 --- a/src/Domain/Folders/Resources/FolderResource.php +++ b/src/Domain/Folders/Resources/FolderResource.php @@ -26,6 +26,7 @@ class FolderResource extends JsonResource 'trashed_items' => $this->trashed_items, 'updated_at' => $this->updated_at, 'created_at' => Carbon::parse($this->created_at)->diffForHumans(), + 'deleted_at' => $this->deleted_at ? Carbon::parse($this->deleted_at)->diffForHumans() : null, /*'updated_at' => format_date( set_time_by_user_timezone($this->updated_at), __t('time') ), diff --git a/src/Domain/Localization/Actions/SeedDefaultLanguageAction.php b/src/Domain/Localization/Actions/SeedDefaultLanguageAction.php index a24dd7a6..4757b5cd 100644 --- a/src/Domain/Localization/Actions/SeedDefaultLanguageAction.php +++ b/src/Domain/Localization/Actions/SeedDefaultLanguageAction.php @@ -11,13 +11,15 @@ class SeedDefaultLanguageAction */ public function __invoke(): void { - Language::create([ + Language::updateOrCreate([ 'name' => 'English', + ], [ 'locale' => 'en', ]); - Setting::create([ + Setting::updateOrCreate([ 'name' => 'language', + ], [ 'value' => 'en', ]); } diff --git a/src/Support/Scheduler/Actions/ReportUsageAction.php b/src/Support/Scheduler/Actions/ReportUsageAction.php index 5b4d8812..f736b902 100644 --- a/src/Support/Scheduler/Actions/ReportUsageAction.php +++ b/src/Support/Scheduler/Actions/ReportUsageAction.php @@ -1,8 +1,8 @@ 'fixed', + 'metered' => 'metered', + default => 'default', + }; + } +} + if (! function_exists('get_email_provider')) { /** * Get single or multiple values from settings table @@ -456,18 +470,14 @@ if (! function_exists('format_bytes')) { } } -if (! function_exists('get_storage_fill_percentage')) { +if (! function_exists('get_storage_percentage')) { /** * Get storage usage in percent - * - * @param $used - * @param $from - * @return string */ - function get_storage_fill_percentage($used, $from) + function get_storage_percentage(int $used, int $maxAmount): float { // Format gigabytes to bytes - $total = intval(Metric::gigabytes($from)->numberOfBytes()); + $total = intval(Metric::gigabytes($maxAmount)->numberOfBytes()); // Count progress if ($total == 0) { @@ -485,17 +495,17 @@ if (! function_exists('user_storage_percentage')) { /** * Get user capacity fill by percentage */ - function user_storage_percentage($id, ?int $additionals = null) + function user_storage_percentage($id, ?int $additional = null) { $user = User::findOrFail($id); $used = $user->usedCapacity; - if ($additionals) { - $used = $user->usedCapacity + $additionals; + if ($additional) { + $used = $user->usedCapacity + $additional; } - return get_storage_fill_percentage($used, $user->limitations->max_storage_amount); + return get_storage_percentage($used, $user->limitations->max_storage_amount); } } diff --git a/tests/App/Limitations/DefaultLimitationTest.php b/tests/App/Limitations/DefaultLimitationTest.php new file mode 100644 index 00000000..74e3113d --- /dev/null +++ b/tests/App/Limitations/DefaultLimitationTest.php @@ -0,0 +1,88 @@ +create(); + + $this->assertEquals(true, $user->canUpload(9999999)); + } + + /** + * @test + */ + public function it_cant_upload_because_storage_limit_exceeded() + { + $user = User::factory() + ->create(); + + File::factory() + ->create([ + 'user_id' => $user->id, + 'filesize' => 99999999, + ]); + + $this->assertEquals(false, $user->canUpload(999999999)); + } + + /** + * @test + */ + public function it_can_upload_because_storage_limitation_is_turned_off_and_user_has_unlimited_limit() + { + $user = User::factory() + ->create(); + + // Turn off storage limitation + Setting::updateOrCreate([ + 'name' => 'storage_limitation', + ], [ + 'value' => 0, + ]); + + File::factory() + ->create([ + 'user_id' => $user->id, + 'filesize' => 99999999, + ]); + + $this->assertEquals(1, $user->limitations->max_storage_amount); + $this->assertEquals(true, $user->canUpload(999999999)); + } + + /** + * @test + */ + public function it_cant_upload_because_storage_limitation_is_turned_on_and_user_exceeded_limit() + { + $user = User::factory() + ->create(); + + // Turn on storage limitation + Setting::updateOrCreate([ + 'name' => 'storage_limitation', + ], [ + 'value' => 1, + ]); + + File::factory() + ->create([ + 'user_id' => $user->id, + 'filesize' => 99999999, + ]); + + $this->assertEquals(1, $user->limitations->max_storage_amount); + $this->assertEquals(false, $user->canUpload(999999999)); + } +} diff --git a/tests/App/Limitations/FixedBillingLimitationTest.php b/tests/App/Limitations/FixedBillingLimitationTest.php new file mode 100644 index 00000000..e4024042 --- /dev/null +++ b/tests/App/Limitations/FixedBillingLimitationTest.php @@ -0,0 +1,49 @@ + 'subscription_type', + ], [ + 'value' => 'fixed', + ]); + } + + /** + * @test + */ + public function it_can_upload() + { + $user = User::factory() + ->create(); + + $this->assertEquals(true, $user->canUpload(9999999)); + } + + /** + * @test + */ + public function it_cant_upload_because_storage_limit_exceeded() + { + $user = User::factory() + ->create(); + + File::factory() + ->create([ + 'user_id' => $user->id, + 'filesize' => 99999999, + ]); + + $this->assertEquals(false, $user->canUpload(999999999)); + } +} diff --git a/tests/App/Limitations/LimitationTest.php b/tests/App/Limitations/LimitationTest.php new file mode 100644 index 00000000..d80753b0 --- /dev/null +++ b/tests/App/Limitations/LimitationTest.php @@ -0,0 +1,47 @@ + 'subscription_type', + ], [ + 'value' => 'metered', + ]); + + $this->assertEquals('metered', get_limitation_driver()); + } + /** + * @test + */ + public function it_get_fixed_driver() + { + Setting::updateOrCreate([ + 'name' => 'subscription_type', + ], [ + 'value' => 'fixed', + ]); + + $this->assertEquals('fixed', get_limitation_driver()); + } + /** + * @test + */ + public function it_get_default_driver() + { + $subscriptionType = Setting::where('name', 'subscription_type') + ->first(); + + $subscriptionType?->delete(); + + $this->assertEquals('default', get_limitation_driver()); + } +} diff --git a/tests/App/Limitations/MeteredBillingLimitationTest.php b/tests/App/Limitations/MeteredBillingLimitationTest.php new file mode 100644 index 00000000..a7826217 --- /dev/null +++ b/tests/App/Limitations/MeteredBillingLimitationTest.php @@ -0,0 +1,43 @@ +insert([ + 'name' => 'subscription_type', + 'value' => 'metered', + ]); + } + + /** + * @test + */ + public function it_can_upload() + { + $user = User::factory() + ->hasFailedpayments(2) + ->create(); + + $this->assertEquals(true, $user->canUpload()); + } + + /** + * @test + */ + public function it_cant_upload_because_user_has_3_failed_payments() + { + $user = User::factory() + ->hasFailedpayments(3) + ->create(); + + $this->assertEquals(false, $user->canUpload()); + } +} diff --git a/tests/Domain/Admin/AdminTest.php b/tests/Domain/Admin/AdminTest.php index f5689244..432c9b76 100644 --- a/tests/Domain/Admin/AdminTest.php +++ b/tests/Domain/Admin/AdminTest.php @@ -269,7 +269,7 @@ class AdminTest extends TestCase }); // Create shares - Share::factory(Share::class) + Share::factory() ->count(2) ->create(['user_id' => $user->id]); diff --git a/tests/Domain/Admin/DashboardTest.php b/tests/Domain/Admin/DashboardTest.php index 718503d5..3e2669b5 100644 --- a/tests/Domain/Admin/DashboardTest.php +++ b/tests/Domain/Admin/DashboardTest.php @@ -5,7 +5,6 @@ use Tests\TestCase; use App\Users\Models\User; use Laravel\Sanctum\Sanctum; use Domain\Files\Models\File; -use Domain\Settings\Models\Setting; class DashboardTest extends TestCase { @@ -21,17 +20,12 @@ class DashboardTest extends TestCase ->count(2) ->create(['filesize' => 1000000]); - Setting::forceCreate([ - 'name' => 'license', - 'value' => 'Regular', - ]); - $this ->actingAs($user) ->getJson('/api/admin/dashboard') ->assertStatus(200) ->assertExactJson([ - 'license' => 'Regular', + 'license' => 'extended', 'total_premium_users' => 0, 'app_version' => config('vuefilemanager.version'), 'total_users' => 1, diff --git a/tests/Domain/Browsing/BrowseTest.php b/tests/Domain/Browsing/BrowseTest.php index 64c1b0a1..bd72a194 100644 --- a/tests/Domain/Browsing/BrowseTest.php +++ b/tests/Domain/Browsing/BrowseTest.php @@ -296,14 +296,14 @@ class BrowseTest extends TestCase 'user_id' => $user->id, ]); - Share::factory(Share::class) + Share::factory() ->create([ 'type' => 'folder', 'item_id' => $folder->id, 'user_id' => $user->id, ]); - Share::factory(Share::class) + Share::factory() ->create([ 'type' => 'file', 'item_id' => $file->id, diff --git a/tests/Domain/Files/FileTest.php b/tests/Domain/Files/FileTest.php index 141f75ec..66030bee 100644 --- a/tests/Domain/Files/FileTest.php +++ b/tests/Domain/Files/FileTest.php @@ -103,11 +103,6 @@ class FileTest extends TestCase */ public function user_with_full_storage_capacity_try_to_upload_new_file() { - Setting::create([ - 'name' => 'storage_limitation', - 'value' => 1, - ]); - $file = UploadedFile::fake() ->image('fake-file.jpeg', 1000); diff --git a/tests/Domain/Homepage/HomepageTest.php b/tests/Domain/Homepage/HomepageTest.php index f429d119..02852151 100644 --- a/tests/Domain/Homepage/HomepageTest.php +++ b/tests/Domain/Homepage/HomepageTest.php @@ -28,11 +28,6 @@ class HomepageTest extends TestCase 'value' => 'setup-done', ]); - Setting::create([ - 'name' => 'license', - 'value' => 'Extended', - ]); - $this->get('/') ->assertStatus(200) ->assertSee('setup-done') @@ -64,7 +59,7 @@ class HomepageTest extends TestCase 'name' => 'Folder Title', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $user->id, @@ -125,7 +120,7 @@ class HomepageTest extends TestCase 'type' => 'image', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $user->id, diff --git a/tests/Domain/Languages/AdminLanguageTranslatorTest.php b/tests/Domain/Languages/AdminLanguageTranslatorTest.php index c01d9342..b795d28d 100644 --- a/tests/Domain/Languages/AdminLanguageTranslatorTest.php +++ b/tests/Domain/Languages/AdminLanguageTranslatorTest.php @@ -3,7 +3,6 @@ namespace Tests\Domain\Languages; use Tests\TestCase; use App\Users\Models\User; -use Domain\Settings\Models\Setting; use Domain\Localization\Models\Language; use Domain\Localization\Actions\SeedDefaultLanguageAction; @@ -14,11 +13,6 @@ class AdminLanguageTranslatorTest extends TestCase */ public function it_create_language() { - Setting::create([ - 'name' => 'license', - 'value' => 'Extended', - ]); - $admin = User::factory() ->create(['role' => 'admin']); diff --git a/tests/Domain/Maintenance/AppUpgradeTest.php b/tests/Domain/Maintenance/AppUpgradeTest.php index da269285..f8652678 100644 --- a/tests/Domain/Maintenance/AppUpgradeTest.php +++ b/tests/Domain/Maintenance/AppUpgradeTest.php @@ -16,18 +16,6 @@ class AppUpgradeTest extends TestCase $user = User::factory() ->create(['role' => 'admin']); - DB::table('settings') - ->insert([ - [ - 'name' => 'language', - 'value' => 'en', - ], - [ - 'name' => 'license', - 'value' => 'Extended', - ], - ]); - collect(['en', 'sk']) ->map(function ($locale) { DB::table('languages') diff --git a/tests/Domain/SetupWizard/SetupWizardTest.php b/tests/Domain/SetupWizard/SetupWizardTest.php index de75082d..ad5741ac 100644 --- a/tests/Domain/SetupWizard/SetupWizardTest.php +++ b/tests/Domain/SetupWizard/SetupWizardTest.php @@ -154,6 +154,8 @@ class SetupWizardTest extends TestCase */ public function it_store_app_settings() { + Setting::all()->each->delete(); + $this->postJson('/api/setup/app-setup', [ 'title' => 'VueFileManager', 'description' => 'The best file manager on the internet', @@ -207,6 +209,8 @@ class SetupWizardTest extends TestCase */ public function it_create_admin_account() { + Setting::all()->each->delete(); + $this->post('/admin-setup', [ 'email' => 'john@doe.com', 'password' => 'VerySecretPassword', diff --git a/tests/Domain/Sharing/VisitorAccessToItemsTest.php b/tests/Domain/Sharing/VisitorAccessToItemsTest.php index f394a2a3..44f7b33b 100644 --- a/tests/Domain/Sharing/VisitorAccessToItemsTest.php +++ b/tests/Domain/Sharing/VisitorAccessToItemsTest.php @@ -34,7 +34,7 @@ class VisitorAccessToItemsTest extends TestCase 'name' => $document->name, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $user->id, @@ -75,7 +75,7 @@ class VisitorAccessToItemsTest extends TestCase 'name' => 'fake-thumbnail.jpg', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'type' => 'file', 'is_protected' => true, @@ -114,7 +114,7 @@ class VisitorAccessToItemsTest extends TestCase 'mimetype' => 'jpg', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $user->id, @@ -166,7 +166,7 @@ class VisitorAccessToItemsTest extends TestCase 'basename' => $fileName, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $user->id, diff --git a/tests/Domain/Sharing/VisitorBrowseTest.php b/tests/Domain/Sharing/VisitorBrowseTest.php index 43e70a66..ab7e78e8 100644 --- a/tests/Domain/Sharing/VisitorBrowseTest.php +++ b/tests/Domain/Sharing/VisitorBrowseTest.php @@ -14,7 +14,7 @@ class VisitorBrowseTest extends TestCase */ public function it_get_share_record() { - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'is_protected' => 0, ]); @@ -43,7 +43,7 @@ class VisitorBrowseTest extends TestCase */ public function it_get_share_page() { - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'type' => 'folder', 'is_protected' => false, @@ -80,7 +80,7 @@ class VisitorBrowseTest extends TestCase $file = File::factory() ->create(); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $file->user_id, @@ -107,7 +107,7 @@ class VisitorBrowseTest extends TestCase $file = File::factory() ->create(); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $file->user_id, @@ -140,7 +140,7 @@ class VisitorBrowseTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $root->id, 'user_id' => $user->id, @@ -219,7 +219,7 @@ class VisitorBrowseTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder_level_1->id, 'user_id' => $user->id, @@ -322,7 +322,7 @@ class VisitorBrowseTest extends TestCase $folder = Folder::factory(Folder::class) ->create(); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $folder->user_id, @@ -376,7 +376,7 @@ class VisitorBrowseTest extends TestCase $folder = Folder::factory(Folder::class) ->create(); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $folder->user_id, @@ -427,7 +427,7 @@ class VisitorBrowseTest extends TestCase 'name' => 'Document', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $file->user_id, diff --git a/tests/Domain/Sharing/VisitorManipulatingTest.php b/tests/Domain/Sharing/VisitorManipulatingTest.php index 965e7db3..8314bfe3 100644 --- a/tests/Domain/Sharing/VisitorManipulatingTest.php +++ b/tests/Domain/Sharing/VisitorManipulatingTest.php @@ -33,7 +33,7 @@ class VisitorManipulatingTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $user->id, @@ -102,7 +102,7 @@ class VisitorManipulatingTest extends TestCase 'parent_id' => $root->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $root->id, 'user_id' => $user->id, @@ -165,7 +165,7 @@ class VisitorManipulatingTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $user->id, @@ -229,7 +229,7 @@ class VisitorManipulatingTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $user->id, @@ -305,7 +305,7 @@ class VisitorManipulatingTest extends TestCase 'author' => 'user', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $user->id, @@ -385,7 +385,7 @@ class VisitorManipulatingTest extends TestCase 'parent_id' => $root->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $root->id, 'user_id' => $user->id, @@ -458,7 +458,7 @@ class VisitorManipulatingTest extends TestCase 'parent_id' => $root->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $root->id, 'user_id' => $user->id, diff --git a/tests/Domain/Traffic/TrafficTest.php b/tests/Domain/Traffic/TrafficTest.php index f40771b8..1919c388 100644 --- a/tests/Domain/Traffic/TrafficTest.php +++ b/tests/Domain/Traffic/TrafficTest.php @@ -102,7 +102,7 @@ class TrafficTest extends TestCase 'author' => 'user', ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $this->user->id, @@ -172,7 +172,7 @@ class TrafficTest extends TestCase 'name' => $document->name, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $file->id, 'user_id' => $this->user->id, diff --git a/tests/Domain/Zip/SharedZippingTest.php b/tests/Domain/Zip/SharedZippingTest.php index fe3dcd81..c4a315ee 100644 --- a/tests/Domain/Zip/SharedZippingTest.php +++ b/tests/Domain/Zip/SharedZippingTest.php @@ -68,7 +68,7 @@ class SharedZippingTest extends TestCase ]); }); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $sharedFolder->id, 'user_id' => $user->id, @@ -131,7 +131,7 @@ class SharedZippingTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $folder->id, 'user_id' => $user->id, @@ -206,7 +206,7 @@ class SharedZippingTest extends TestCase ]); }); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $children->id, 'user_id' => $user->id, @@ -251,7 +251,7 @@ class SharedZippingTest extends TestCase 'user_id' => $user->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'user_id' => $user->id, 'type' => 'folder', diff --git a/tests/Support/Gate/GateTest.php b/tests/Support/Gate/GateTest.php index 46edaa98..c0a7c074 100644 --- a/tests/Support/Gate/GateTest.php +++ b/tests/Support/Gate/GateTest.php @@ -61,7 +61,7 @@ class GateTest extends TestCase 'parent_id' => $root->id, ]); - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'item_id' => $root->id, 'user_id' => $user->id, diff --git a/tests/Support/Scheduler/SchedulerTest.php b/tests/Support/Scheduler/SchedulerTest.php index 23f5f2f8..8cbc6073 100644 --- a/tests/Support/Scheduler/SchedulerTest.php +++ b/tests/Support/Scheduler/SchedulerTest.php @@ -84,7 +84,7 @@ class SchedulerTest extends TestCase */ public function it_delete_expired_shared_links() { - $share = Share::factory(Share::class) + $share = Share::factory() ->create([ 'expire_in' => 24, 'created_at' => now()->subDay(), diff --git a/tests/TestCase.php b/tests/TestCase.php index c1648da8..373e3d1a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,6 +1,7 @@ storeDefaultSettings(); + //$this->withoutExceptionHandling(); } + + public function storeDefaultSettings() + { + DB::table('settings')->insert([ + [ + 'name' => 'storage_limitation', + 'value' => 1, + ], + [ + 'name' => 'license', + 'value' => 'extended', + ], + [ + 'name' => 'language', + 'value' => 'en', + ], + ]); + } }