mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
deleted pro files
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
"php": "^8.0.2",
|
||||
"ext-json": "*",
|
||||
"ext-pdo": "*",
|
||||
"beyondcode/laravel-websockets": "^1.13",
|
||||
"brianium/paratest": "^6.4.1",
|
||||
"cocur/slugify": "^4.1",
|
||||
"doctrine/dbal": "^2.13.7",
|
||||
@@ -24,14 +23,11 @@
|
||||
"laravel/fortify": "^1.12.0",
|
||||
"laravel/framework": "^9.2",
|
||||
"laravel/sanctum": "^2.14.2",
|
||||
"laravel/socialite": "^5.5.1",
|
||||
"laravel/tinker": "^2.7",
|
||||
"laravel/ui": "^3.4.2",
|
||||
"league/flysystem-aws-s3-v3": "^3.0.9",
|
||||
"league/flysystem-ftp": "^3.0",
|
||||
"makingcg/subscription": "^1.0.5",
|
||||
"matthewbdaly/laravel-azure-storage": "^2.0",
|
||||
"pusher/pusher-php-server": "^7.0",
|
||||
"spatie/data-transfer-object": "^3.7.3",
|
||||
"spatie/laravel-backup": "^8.0.8",
|
||||
"spatie/laravel-query-builder": "^5.0.0",
|
||||
@@ -55,12 +51,6 @@
|
||||
"fakerphp/faker": "^1.19.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/VueFileManager/subscription.git"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
|
||||
2840
composer.lock
generated
2840
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -161,7 +161,6 @@ return [
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
|
||||
TeamTNT\Scout\TNTSearchScoutServiceProvider::class,
|
||||
Laravel\Socialite\SocialiteServiceProvider::class,
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
App\Providers\FortifyServiceProvider::class,
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Domain\Teams\Controllers\InvitationsController;
|
||||
use Domain\Teams\Controllers\TeamFoldersController;
|
||||
use Domain\Teams\Controllers\NavigationTreeController;
|
||||
use Domain\Teams\Controllers\LeaveTeamFolderController;
|
||||
use Domain\Teams\Controllers\BrowseSharedWithMeController;
|
||||
use Domain\Teams\Controllers\ConvertFolderIntoTeamFolderController;
|
||||
|
||||
Route::apiResource('/invitations', InvitationsController::class);
|
||||
|
||||
Route::group(['middleware' => ['auth:sanctum']], function () {
|
||||
Route::get('/shared-with-me/{id}', BrowseSharedWithMeController::class);
|
||||
Route::apiResource('/folders', TeamFoldersController::class);
|
||||
|
||||
Route::post('/folders/{folder}/convert', ConvertFolderIntoTeamFolderController::class);
|
||||
Route::delete('/folders/{folder}/leave', LeaveTeamFolderController::class);
|
||||
Route::get('/folders/{folder}/tree', NavigationTreeController::class);
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Domain\UploadRequest\Controllers\CreateFolderController;
|
||||
use Domain\UploadRequest\Controllers\GetUploadRequestController;
|
||||
use Domain\UploadRequest\Controllers\DeleteFileOrFolderController;
|
||||
use Domain\UploadRequest\Controllers\RenameFileOrFolderController;
|
||||
use Domain\UploadRequest\Controllers\BrowseUploadRequestController;
|
||||
use Domain\UploadRequest\Controllers\CreateUploadRequestController;
|
||||
use Domain\UploadRequest\Controllers\MoveItemInUploadRequestController;
|
||||
use Domain\UploadRequest\Controllers\SetUploadRequestAsFilledController;
|
||||
use Domain\UploadRequest\Controllers\UploadFilesForUploadRequestController;
|
||||
use Domain\UploadRequest\Controllers\GetFolderTreeForUploadRequestController;
|
||||
use Domain\RemoteUpload\Controllers\UploadFilesRemotelyForUploadRequestController;
|
||||
|
||||
Route::get('/{uploadRequest}', GetUploadRequestController::class);
|
||||
|
||||
// Available only for active upload requests
|
||||
Route::group(['middleware' => 'upload-request'], function () {
|
||||
// Detail
|
||||
Route::delete('/{uploadRequest}', SetUploadRequestAsFilledController::class);
|
||||
|
||||
// Edit
|
||||
Route::post('/{uploadRequest}/upload/remote', UploadFilesRemotelyForUploadRequestController::class);
|
||||
Route::post('/{uploadRequest}/upload', UploadFilesForUploadRequestController::class);
|
||||
Route::patch('/{uploadRequest}/rename/{id}', RenameFileOrFolderController::class);
|
||||
Route::post('/{uploadRequest}/create-folder', CreateFolderController::class);
|
||||
Route::post('/{uploadRequest}/remove', DeleteFileOrFolderController::class);
|
||||
|
||||
// Browsing
|
||||
Route::get('/{uploadRequest}/navigation', GetFolderTreeForUploadRequestController::class);
|
||||
Route::get('/{uploadRequest}/browse/{folder?}', BrowseUploadRequestController::class);
|
||||
Route::post('/{uploadRequest}/move', MoveItemInUploadRequestController::class);
|
||||
});
|
||||
|
||||
// User functionality
|
||||
Route::group(['middleware' => ['auth:sanctum']], function () {
|
||||
Route::post('/', CreateUploadRequestController::class);
|
||||
});
|
||||
@@ -1,569 +0,0 @@
|
||||
<?php
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use DB;
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Console\Command;
|
||||
use Domain\Settings\Models\Setting;
|
||||
use VueFileManager\Subscription\Domain\Plans\Models\Plan;
|
||||
use VueFileManager\Subscription\Domain\CreditCards\Models\CreditCard;
|
||||
use VueFileManager\Subscription\Domain\Plans\DTO\CreateFixedPlanData;
|
||||
use VueFileManager\Subscription\Domain\Plans\DTO\CreateMeteredPlanData;
|
||||
use VueFileManager\Subscription\Domain\Subscriptions\Models\Subscription;
|
||||
use VueFileManager\Subscription\Domain\Plans\Actions\StoreFixedPlanAction;
|
||||
use VueFileManager\Subscription\Domain\Plans\Actions\StoreMeteredPlanAction;
|
||||
|
||||
class GenerateDemoSubscriptionContentCommand extends Command
|
||||
{
|
||||
public $signature = 'subscription:demo {type=fixed}';
|
||||
|
||||
public $description = 'Generate demo content for subscription module';
|
||||
|
||||
public function __construct(
|
||||
private StoreFixedPlanAction $storeFixedPlan,
|
||||
private StoreMeteredPlanAction $storeMeteredPlan,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
// Truncate all subscription relate tables
|
||||
collect([
|
||||
'balances', 'billing_alerts', 'credit_cards', 'customers', 'failed_payments', 'metered_tiers', 'plan_drivers', 'plan_fixed_features', 'plan_metered_features', 'plans', 'subscription_drivers', 'subscriptions', 'usages', 'transactions',
|
||||
])->each(fn ($name) => DB::table($name)->truncate());
|
||||
|
||||
// Create plans and subscriptions for metered billing
|
||||
if ($this->argument('type') === 'metered') {
|
||||
$this->info('Setting up new metered plans demo data...');
|
||||
$this->generateMeteredPlans();
|
||||
|
||||
$this->info('Setting up new pre-paid subscriptions data...');
|
||||
$this->generateMeteredSubscription();
|
||||
}
|
||||
|
||||
// Create plans and subscriptions for fixed billing
|
||||
if ($this->argument('type') === 'fixed') {
|
||||
// TODO: check for credentials
|
||||
|
||||
$this->info('Setting up new fixed plans demo data...');
|
||||
$this->generateFixedPlans();
|
||||
|
||||
$this->info('Setting up new fixed subscriptions data...');
|
||||
$this->generateFixedSubscription();
|
||||
}
|
||||
|
||||
// Set subscription type for the app
|
||||
Setting::updateOrCreate([
|
||||
'name' => 'subscription_type',
|
||||
], [
|
||||
'value' => $this->argument('type'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function generateMeteredSubscription(): void
|
||||
{
|
||||
$plan = Plan::where('name', 'Pay as You Go')
|
||||
->first();
|
||||
|
||||
User::all()
|
||||
->each(function ($user) use ($plan) {
|
||||
$isHowdy = $user->email === 'howdy@hi5ve.digital';
|
||||
|
||||
$this->info("Storing {$plan->name} for {$user->email}...");
|
||||
|
||||
// 1. Create subscription
|
||||
$subscription = Subscription::create([
|
||||
'user_id' => $user->id,
|
||||
'type' => 'pre-paid',
|
||||
'plan_id' => $plan->id,
|
||||
'name' => $plan->name,
|
||||
'status' => 'active',
|
||||
'renews_at' => now()->addDays(16),
|
||||
'created_at' => now()->subDays(14),
|
||||
'updated_at' => now()->subDays(14),
|
||||
]);
|
||||
|
||||
// 2. Log fake storage and bandwidth
|
||||
foreach (range(1, 31) as $item) {
|
||||
$this->info('Logging fake bandwidth usage...');
|
||||
|
||||
$bandwidthFeature = $plan
|
||||
->meteredFeatures()
|
||||
->where('key', 'bandwidth')
|
||||
->first();
|
||||
|
||||
$subscription->usages()->create([
|
||||
'metered_feature_id' => $bandwidthFeature->id,
|
||||
'quantity' => random_int(111, 999) / 1000,
|
||||
'created_at' => now()->subDays($item),
|
||||
]);
|
||||
|
||||
$this->info('Logging fake storage usage...');
|
||||
|
||||
$storageFeature = $plan
|
||||
->meteredFeatures()
|
||||
->where('key', 'storage')
|
||||
->first();
|
||||
|
||||
$subscription->usages()->create([
|
||||
'metered_feature_id' => $storageFeature->id,
|
||||
'quantity' => random_int(1111, 3999) / 1000,
|
||||
'created_at' => now()->subDays($item),
|
||||
]);
|
||||
}
|
||||
|
||||
// 3. Store flat fee
|
||||
$flatFeeFeature = $plan
|
||||
->meteredFeatures()
|
||||
->where('key', 'flatFee')
|
||||
->first();
|
||||
|
||||
$subscription->usages()->create([
|
||||
'metered_feature_id' => $flatFeeFeature->id,
|
||||
'quantity' => 1,
|
||||
'created_at' => now()->subDays(2),
|
||||
]);
|
||||
|
||||
// 4. Store member count
|
||||
$memberFeature = $plan
|
||||
->meteredFeatures()
|
||||
->where('key', 'member')
|
||||
->first();
|
||||
|
||||
$subscription->usages()->create([
|
||||
'metered_feature_id' => $memberFeature->id,
|
||||
'quantity' => 7,
|
||||
'created_at' => now()->subDays(2),
|
||||
]);
|
||||
|
||||
// 5. Store fake transactions
|
||||
$this->info("Storing transactions for {$user->email}...");
|
||||
|
||||
collect([
|
||||
[
|
||||
'type' => 'withdrawal',
|
||||
'created_at' => now()->subDays(2),
|
||||
'amount' => $isHowdy ? 12.59 : random_int(1, 20),
|
||||
'note' => now()->subDays(32)->format('d. M') . ' - ' . now()->subDays(2)->format('d. M'),
|
||||
'driver' => 'system',
|
||||
],
|
||||
[
|
||||
'type' => 'credit',
|
||||
'created_at' => now()->subDays(26 * 1),
|
||||
'note' => __('Bonus'),
|
||||
'amount' => $isHowdy ? 12.00 : random_int(1, 20),
|
||||
'driver' => 'system',
|
||||
],
|
||||
[
|
||||
'type' => 'withdrawal',
|
||||
'created_at' => now()->subDays(26 * 1),
|
||||
'note' => now()->subDays(30 + 26 * 1)->format('d. M') . ' - ' . now()->subDays(26 * 1)->format('d. M'),
|
||||
'amount' => $isHowdy ? 2.38 : random_int(1, 20),
|
||||
'driver' => 'system',
|
||||
],
|
||||
[
|
||||
'type' => 'withdrawal',
|
||||
'created_at' => now()->subDays(26 * 2),
|
||||
'note' => now()->subDays(30 + 26 * 2)->format('d. M') . ' - ' . now()->subDays(26 * 2)->format('d. M'),
|
||||
'amount' => $isHowdy ? 5.12 : random_int(1, 20),
|
||||
'driver' => 'system',
|
||||
],
|
||||
[
|
||||
'type' => 'withdrawal',
|
||||
'created_at' => now()->subDays(26 * 3),
|
||||
'note' => now()->subDays(30 + 26 * 3)->format('d. M') . ' - ' . now()->subDays(26 * 3)->format('d. M'),
|
||||
'amount' => $isHowdy ? 3.89 : random_int(1, 20),
|
||||
'driver' => 'system',
|
||||
],
|
||||
[
|
||||
'type' => 'withdrawal',
|
||||
'created_at' => now()->subDays(26 * 4),
|
||||
'note' => now()->subDays(30 + 26 * 4)->format('d. M') . ' - ' . now()->subDays(26 * 4)->format('d. M'),
|
||||
'amount' => $isHowdy ? 7.42 : random_int(1, 20),
|
||||
'driver' => 'system',
|
||||
],
|
||||
[
|
||||
'type' => 'charge',
|
||||
'created_at' => now()->subDays(26 * 5),
|
||||
'note' => 'Account Fund',
|
||||
'amount' => $isHowdy ? 50.00 : random_int(1, 20),
|
||||
'driver' => 'paypal',
|
||||
],
|
||||
])->each(
|
||||
function ($transaction) use ($user, $plan) {
|
||||
$bandwidthUsage = random_int(1000, 12000) / 1000;
|
||||
$storageUsage = random_int(300, 4900) / 1000;
|
||||
$memberUsage = random_int(3, 20);
|
||||
|
||||
$user->transactions()->create([
|
||||
'type' => $transaction['type'],
|
||||
'status' => 'completed',
|
||||
'note' => $transaction['note'],
|
||||
'currency' => $plan->currency,
|
||||
'driver' => $transaction['driver'],
|
||||
'amount' => $transaction['amount'],
|
||||
'created_at' => $transaction['created_at'],
|
||||
'reference' => Str::random(12),
|
||||
'metadata' => $transaction['type'] === 'withdrawal'
|
||||
? [
|
||||
[
|
||||
'feature' => 'bandwidth',
|
||||
'amount' => 0.29 * $bandwidthUsage,
|
||||
'usage' => $bandwidthUsage,
|
||||
],
|
||||
[
|
||||
'feature' => 'storage',
|
||||
'amount' => 0.19 * $storageUsage,
|
||||
'usage' => $storageUsage,
|
||||
],
|
||||
[
|
||||
'feature' => 'flatFee',
|
||||
'amount' => 2.49,
|
||||
'usage' => 1,
|
||||
],
|
||||
[
|
||||
'feature' => 'member',
|
||||
'amount' => 0.10 * $memberUsage,
|
||||
'usage' => $memberUsage,
|
||||
],
|
||||
]
|
||||
: null,
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
// Make fake credit card
|
||||
$creditCard = CreditCard::factory()
|
||||
->make();
|
||||
|
||||
// 6. Store credit card
|
||||
if (! $isHowdy) {
|
||||
$user->creditCards()->create([
|
||||
'brand' => $creditCard->brand,
|
||||
'last4' => $creditCard->last4,
|
||||
'service' => $creditCard->service,
|
||||
'reference' => $creditCard->reference,
|
||||
'expiration' => $creditCard->expiration,
|
||||
]);
|
||||
}
|
||||
|
||||
// 7. Add default user balance
|
||||
$user->balance()->create([
|
||||
'currency' => 'USD',
|
||||
'amount' => $isHowdy ? 30.60 : random_int(20, 60),
|
||||
]);
|
||||
|
||||
// 8. Create billing alert
|
||||
$user->billingAlert()->create([
|
||||
'amount' => $isHowdy ? 25 : random_int(30, 80),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function generateFixedSubscription(): void
|
||||
{
|
||||
$howdy = User::where('email', 'howdy@hi5ve.digital')
|
||||
->first();
|
||||
|
||||
$alice = User::where('email', 'alice@hi5ve.digital')
|
||||
->first();
|
||||
|
||||
$johan = User::where('email', 'johan@hi5ve.digital')
|
||||
->first();
|
||||
|
||||
$professionalPackPlan = Plan::where('name', 'Professional Pack')
|
||||
->where('interval', 'month')
|
||||
->first();
|
||||
|
||||
$businessPackPlan = Plan::where('name', 'Business Pack')
|
||||
->where('interval', 'month')
|
||||
->first();
|
||||
|
||||
$this->info("Storing {$professionalPackPlan->name} for {$howdy->email}...");
|
||||
|
||||
$howdySubscription = $howdy->subscription()->create([
|
||||
'plan_id' => $professionalPackPlan->id,
|
||||
'name' => $professionalPackPlan->name,
|
||||
'status' => 'active',
|
||||
'created_at' => now()->subDays(14),
|
||||
'updated_at' => now()->subDays(14),
|
||||
]);
|
||||
|
||||
$this->info("Storing {$businessPackPlan->name} for {$alice->email}...");
|
||||
|
||||
$aliceSubscription = $alice->subscription()->create([
|
||||
'plan_id' => $businessPackPlan->id,
|
||||
'name' => $businessPackPlan->name,
|
||||
'status' => 'active',
|
||||
'created_at' => now()->subDays(9),
|
||||
'updated_at' => now()->subDays(9),
|
||||
]);
|
||||
|
||||
$this->info("Storing {$professionalPackPlan->name} for {$johan->email}...");
|
||||
|
||||
$johanSubscription = $johan->subscription()->create([
|
||||
'plan_id' => $professionalPackPlan->id,
|
||||
'name' => $professionalPackPlan->name,
|
||||
'status' => 'cancelled',
|
||||
'ends_at' => now()->addDays(18),
|
||||
'created_at' => now()->subDays(8),
|
||||
'updated_at' => now()->subDays(8),
|
||||
]);
|
||||
|
||||
$this->info("Storing transactions for {$howdy->email}...");
|
||||
|
||||
collect([
|
||||
['created_at' => now()->subDays(2)],
|
||||
['created_at' => now()->subDays(26)],
|
||||
['created_at' => now()->subDays(26 * 2)],
|
||||
['created_at' => now()->subDays(26 * 3)],
|
||||
['created_at' => now()->subDays(26 * 4)],
|
||||
['created_at' => now()->subDays(26 * 5)],
|
||||
])->each(
|
||||
fn ($transaction) => $howdy->transactions()->create([
|
||||
'status' => 'completed',
|
||||
'note' => $professionalPackPlan->name,
|
||||
'currency' => $professionalPackPlan->currency,
|
||||
'amount' => $professionalPackPlan->amount,
|
||||
'driver' => 'paypal',
|
||||
'created_at' => $transaction['created_at'],
|
||||
'reference' => Str::random(12),
|
||||
])
|
||||
);
|
||||
|
||||
$this->info("Storing transactions for {$johan->email}...");
|
||||
|
||||
collect([
|
||||
['created_at' => now()->subDay()],
|
||||
['created_at' => now()->subDays(29)],
|
||||
['created_at' => now()->subDays(29 * 2)],
|
||||
['created_at' => now()->subDays(29 * 3)],
|
||||
])->each(
|
||||
fn ($transaction) => $johan->transactions()->create([
|
||||
'status' => 'completed',
|
||||
'note' => $professionalPackPlan->name,
|
||||
'currency' => $professionalPackPlan->currency,
|
||||
'amount' => $professionalPackPlan->amount,
|
||||
'driver' => 'stripe',
|
||||
'created_at' => $transaction['created_at'],
|
||||
'reference' => Str::random(12),
|
||||
])
|
||||
);
|
||||
|
||||
$this->info("Storing transactions for {$alice->email}...");
|
||||
|
||||
collect([
|
||||
['created_at' => now()],
|
||||
['created_at' => now()->subDays(28)],
|
||||
['created_at' => now()->subDays(28 * 2)],
|
||||
['created_at' => now()->subDays(28 * 3)],
|
||||
['created_at' => now()->subDays(28 * 4)],
|
||||
])->each(
|
||||
fn ($transaction) => $alice->transactions()->create([
|
||||
'status' => 'completed',
|
||||
'note' => $businessPackPlan->name,
|
||||
'currency' => $businessPackPlan->currency,
|
||||
'amount' => $businessPackPlan->amount,
|
||||
'driver' => 'paystack',
|
||||
'created_at' => $transaction['created_at'],
|
||||
'reference' => Str::random(12),
|
||||
])
|
||||
);
|
||||
|
||||
$howdySubscription->driver()->create([
|
||||
'driver' => 'stripe',
|
||||
'driver_subscription_id' => Str::random(),
|
||||
]);
|
||||
|
||||
// Make fake credit card
|
||||
$creditCard = CreditCard::factory()
|
||||
->make();
|
||||
|
||||
// 6. Store credit card
|
||||
$howdy->creditCards()->create([
|
||||
'brand' => $creditCard->brand,
|
||||
'last4' => $creditCard->last4,
|
||||
'service' => $creditCard->service,
|
||||
'reference' => $creditCard->reference,
|
||||
'expiration' => $creditCard->expiration,
|
||||
]);
|
||||
|
||||
$aliceSubscription->driver()->create([
|
||||
'driver' => 'paystack',
|
||||
'driver_subscription_id' => Str::random(),
|
||||
]);
|
||||
|
||||
$johanSubscription->driver()->create([
|
||||
'driver' => 'stripe',
|
||||
'driver_subscription_id' => Str::random(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function generateFixedPlans()
|
||||
{
|
||||
// Define plans
|
||||
$plans = [
|
||||
[
|
||||
'type' => 'fixed',
|
||||
'name' => 'Professional Pack',
|
||||
'description' => 'Best for all professionals',
|
||||
'currency' => 'USD',
|
||||
'features' => [
|
||||
'max_storage_amount' => 200,
|
||||
'max_team_members' => 20,
|
||||
],
|
||||
'intervals' => [
|
||||
[
|
||||
'interval' => 'month',
|
||||
'amount' => 9.99,
|
||||
],
|
||||
[
|
||||
'interval' => 'year',
|
||||
'amount' => 99.49,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'type' => 'fixed',
|
||||
'name' => 'Business Pack',
|
||||
'description' => 'Best for business needs',
|
||||
'currency' => 'USD',
|
||||
'features' => [
|
||||
'max_storage_amount' => 500,
|
||||
'max_team_members' => 50,
|
||||
],
|
||||
'intervals' => [
|
||||
[
|
||||
'interval' => 'month',
|
||||
'amount' => 29.99,
|
||||
],
|
||||
[
|
||||
'interval' => 'year',
|
||||
'amount' => 189.99,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'type' => 'fixed',
|
||||
'name' => 'Elite Pack',
|
||||
'description' => 'Best for all your needs',
|
||||
'currency' => 'USD',
|
||||
'features' => [
|
||||
'max_storage_amount' => 2000,
|
||||
'max_team_members' => -1,
|
||||
],
|
||||
'intervals' => [
|
||||
[
|
||||
'interval' => 'month',
|
||||
'amount' => 59.99,
|
||||
],
|
||||
[
|
||||
'interval' => 'year',
|
||||
'amount' => 349.99,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Create plans
|
||||
foreach ($plans as $plan) {
|
||||
foreach ($plan['intervals'] as $interval) {
|
||||
$data = CreateFixedPlanData::fromArray([
|
||||
'type' => $plan['type'],
|
||||
'name' => $plan['name'],
|
||||
'description' => $plan['description'],
|
||||
'features' => $plan['features'],
|
||||
'currency' => $plan['currency'],
|
||||
'amount' => $interval['amount'],
|
||||
'interval' => $interval['interval'],
|
||||
]);
|
||||
|
||||
$this->info("Creating plan with name: {$plan['name']} and interval: {$interval['interval']}");
|
||||
|
||||
// Store plans to the database and gateway
|
||||
($this->storeFixedPlan)($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function generateMeteredPlans()
|
||||
{
|
||||
// Define plans
|
||||
$plans = [
|
||||
[
|
||||
'type' => 'metered',
|
||||
'name' => 'Pay as You Go',
|
||||
'description' => 'Best for all professionals',
|
||||
'currency' => 'USD',
|
||||
'meters' => [
|
||||
[
|
||||
'key' => 'bandwidth',
|
||||
'aggregate_strategy' => 'sum_of_usage',
|
||||
'tiers' => [
|
||||
[
|
||||
'first_unit' => 1,
|
||||
'last_unit' => null,
|
||||
'per_unit' => 0.29,
|
||||
'flat_fee' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'key' => 'storage',
|
||||
'aggregate_strategy' => 'maximum_usage',
|
||||
'tiers' => [
|
||||
[
|
||||
'first_unit' => 1,
|
||||
'last_unit' => null,
|
||||
'per_unit' => 0.19,
|
||||
'flat_fee' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'key' => 'flatFee',
|
||||
'aggregate_strategy' => 'maximum_usage',
|
||||
'tiers' => [
|
||||
[
|
||||
'first_unit' => 1,
|
||||
'last_unit' => null,
|
||||
'per_unit' => 2.49,
|
||||
'flat_fee' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'key' => 'member',
|
||||
'aggregate_strategy' => 'maximum_usage',
|
||||
'tiers' => [
|
||||
[
|
||||
'first_unit' => 1,
|
||||
'last_unit' => null,
|
||||
'per_unit' => 0.10,
|
||||
'flat_fee' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Create plans
|
||||
foreach ($plans as $plan) {
|
||||
$data = CreateMeteredPlanData::fromArray([
|
||||
'type' => $plan['type'],
|
||||
'name' => $plan['name'],
|
||||
'meters' => $plan['meters'],
|
||||
'currency' => $plan['currency'],
|
||||
'description' => $plan['description'],
|
||||
]);
|
||||
|
||||
$this->info("Creating plan with name: {$plan['name']}");
|
||||
|
||||
// Store plans to the database and gateway
|
||||
($this->storeMeteredPlan)($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SetupWebsocketEnvironment extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*/
|
||||
protected $signature = 'websockets:install';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Set up websocket production environment';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
// Get allowed origins
|
||||
$origins = $this->ask('Type host of which you want to allow incoming requests. If you want to accept multiple hosts, separate them with comma(,)');
|
||||
|
||||
// Store origins to the .env file
|
||||
setEnvironmentValue([
|
||||
'PUSHER_APP_ALLOWED_ORIGIN' => $origins,
|
||||
'APP_ENV' => 'production',
|
||||
'APP_DEBUG' => 'false',
|
||||
]);
|
||||
|
||||
$this->info('Your host/s was stored successfully.');
|
||||
|
||||
// Generate new app key
|
||||
$this->call('key:generate', [
|
||||
'--force' => true,
|
||||
]);
|
||||
|
||||
// Clear cache
|
||||
$this->call('config:clear');
|
||||
|
||||
$this->info('Everything is done, congratulations! 🥳🥳🥳');
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
namespace App\Socialite\Controllers;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use App\Users\DTO\CreateUserData;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use App\Users\Actions\CreateNewUserAction;
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use VueFileManager\Subscription\Domain\Plans\Models\Plan;
|
||||
use VueFileManager\Subscription\Domain\Plans\Exceptions\MeteredBillingPlanDoesntExist;
|
||||
|
||||
class SocialiteCallbackController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
protected StatefulGuard $guard,
|
||||
public CreateNewUserAction $createNewUser,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MeteredBillingPlanDoesntExist
|
||||
*/
|
||||
public function __invoke($provider)
|
||||
{
|
||||
$isAllowedRegistration = intval(get_settings('registration'));
|
||||
|
||||
// Get socialite user
|
||||
if (app()->runningUnitTests()) {
|
||||
$socialite = Socialite::driver($provider)->user();
|
||||
} else {
|
||||
$socialite = Socialite::driver($provider)->stateless()->user();
|
||||
}
|
||||
|
||||
// Get user by email
|
||||
$user = User::where('email', $socialite->email);
|
||||
|
||||
// Login user when exists
|
||||
if ($user->exists()) {
|
||||
$this->guard->login(
|
||||
$user->first()
|
||||
);
|
||||
|
||||
return redirect()->to('/platform/files');
|
||||
}
|
||||
|
||||
// Check for metered billing plan
|
||||
if (get_settings('subscription_type') === 'metered') {
|
||||
// Get metered plan
|
||||
$plan = Plan::where('status', 'active')
|
||||
->where('type', 'metered');
|
||||
|
||||
// TODO: redirect to the error page
|
||||
if ($plan->doesntExist()) {
|
||||
return response([
|
||||
'type' => 'error',
|
||||
'message' => 'User registrations are temporarily disabled',
|
||||
], 409);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if account registration is enabled
|
||||
if (! $isAllowedRegistration) {
|
||||
return response([
|
||||
'type' => 'error',
|
||||
'message' => 'User registration is not allowed',
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Create data user data object
|
||||
$data = CreateUserData::fromArray([
|
||||
'role' => 'user',
|
||||
'name' => $socialite->getName(),
|
||||
'email' => $socialite->getEmail(),
|
||||
'avatar' => store_socialite_avatar($socialite->getAvatar()),
|
||||
'oauth_provider' => $provider,
|
||||
]);
|
||||
|
||||
// Create User
|
||||
$newUser = ($this->createNewUser)($data);
|
||||
|
||||
// Login user
|
||||
$this->guard->login($newUser);
|
||||
|
||||
return redirect()->to('/platform/files');
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
namespace App\Socialite\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
|
||||
class SocialiteRedirectController extends Controller
|
||||
{
|
||||
public function __invoke($provider)
|
||||
{
|
||||
$url = Socialite::driver($provider)->stateless()->redirect()->getTargetUrl();
|
||||
|
||||
return response()->json([
|
||||
'url' => $url,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
namespace App\Users\Actions;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use VueFileManager\Subscription\Domain\Plans\Models\Plan;
|
||||
use App\Users\Notifications\RegistrationBonusAddedNotification;
|
||||
|
||||
class AutoSubscribeForMeteredBillingAction
|
||||
{
|
||||
public function __invoke(User $user)
|
||||
{
|
||||
// Get metered billing plan
|
||||
$plan = Plan::where('status', 'active')
|
||||
->where('type', 'metered')
|
||||
->first();
|
||||
|
||||
// Get settings
|
||||
$settings = get_settings([
|
||||
'allowed_registration_bonus',
|
||||
'registration_bonus_amount',
|
||||
]);
|
||||
|
||||
// Create user balance
|
||||
if (intval($settings['allowed_registration_bonus'])) {
|
||||
// Create balance with bonus amount
|
||||
$user->balance()->create([
|
||||
'amount' => $settings['registration_bonus_amount'],
|
||||
'currency' => $plan->currency,
|
||||
]);
|
||||
|
||||
// Store transaction bonus
|
||||
$user->transactions()->create([
|
||||
'status' => 'completed',
|
||||
'type' => 'credit',
|
||||
'driver' => 'system',
|
||||
'note' => __t('registration_bonus'),
|
||||
'currency' => $plan->currency,
|
||||
'amount' => $settings['registration_bonus_amount'],
|
||||
]);
|
||||
|
||||
// Send user bonus notification
|
||||
$bonus = format_currency($settings['registration_bonus_amount'], $plan->currency);
|
||||
|
||||
$user->notify(new RegistrationBonusAddedNotification($bonus));
|
||||
} else {
|
||||
// Create balance with 0 amount
|
||||
$user->balance()->create([
|
||||
'amount' => 0,
|
||||
'currency' => $plan->currency,
|
||||
]);
|
||||
}
|
||||
|
||||
// Create user subscription
|
||||
$user->subscription()->create([
|
||||
'plan_id' => $plan->id,
|
||||
'name' => $plan->name,
|
||||
'status' => 'active',
|
||||
'renews_at' => now()->addDays(config('subscription.metered_billing.settlement_period')),
|
||||
'type' => 'pre-paid',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace App\Users\Actions;
|
||||
|
||||
use ByteUnits\Metric;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class FormatUsageEstimatesAction
|
||||
{
|
||||
public function __invoke(string $currency, Collection|array $usage)
|
||||
{
|
||||
return collect($usage)
|
||||
->mapWithKeys(function ($estimate) use ($currency) {
|
||||
// Format usage
|
||||
$usage = match ($estimate['feature']) {
|
||||
'bandwidth', 'storage' => Metric::megabytes($estimate['usage'] * 1000)->format(),
|
||||
'flatFee' => intval($estimate['usage']) . ' ' . __t('pcs.'),
|
||||
'member' => intval($estimate['usage']) . ' ' . __t('mem.'),
|
||||
};
|
||||
|
||||
return [
|
||||
$estimate['feature'] => [
|
||||
'feature' => $estimate['feature'],
|
||||
'amount' => $estimate['amount'],
|
||||
'cost' => format_currency($estimate['amount'], $currency),
|
||||
'usage' => $usage,
|
||||
],
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
namespace App\Users\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class RegistrationBonusAddedNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public string $bonus
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*/
|
||||
public function via(mixed $notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*/
|
||||
public function toArray(mixed $notifiable): array
|
||||
{
|
||||
return [
|
||||
'category' => 'gift',
|
||||
'title' => __t('you_received_bonus', ['bonus' => $this->bonus]),
|
||||
'description' => __t('you_received_registration_bonus_note', ['bonus' => $this->bonus]),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
namespace App\Users\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserSubscription extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$active_subscription = $this->subscription('main')
|
||||
->asStripeSubscription();
|
||||
|
||||
// TODO: vybrat z cache
|
||||
$subscription = resolve('App\Services\StripeService')
|
||||
->getPlan($this->subscription('main')->stripe_plan);
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $subscription['plan']['id'],
|
||||
'type' => 'subscription',
|
||||
'attributes' => [
|
||||
'incomplete' => $this->subscription('main')->incomplete(),
|
||||
'active' => $this->subscription('main')->active(),
|
||||
'canceled' => $this->subscription('main')->cancelled(),
|
||||
'name' => $subscription['product']['name'],
|
||||
'capacity' => (int) $subscription['product']['metadata']['capacity'],
|
||||
'capacity_formatted' => format_gigabytes($subscription['product']['metadata']['capacity']),
|
||||
'slug' => $subscription['plan']['id'],
|
||||
'canceled_at' => format_date($active_subscription['canceled_at'], 'd. M. Y'),
|
||||
'created_at' => format_date($active_subscription['current_period_start'], 'd. M. Y'),
|
||||
'ends_at' => format_date($active_subscription['current_period_end'], 'd. M. Y'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
namespace App\Users\Restrictions\Engines;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use App\Users\Restrictions\RestrictionsEngine;
|
||||
use Domain\Teams\Actions\CheckMaxTeamMembersLimitAction;
|
||||
|
||||
class FixedBillingRestrictionsEngine implements RestrictionsEngine
|
||||
{
|
||||
public function canUpload(User $user, int $fileSize = 0): bool
|
||||
{
|
||||
// Get used capacity
|
||||
$usedPercentage = get_storage_percentage(
|
||||
used: $user->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;
|
||||
}
|
||||
|
||||
public function canCreateTeamFolder(User $user): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canInviteTeamMembers(User $user, array $newInvites = []): bool
|
||||
{
|
||||
return resolve(CheckMaxTeamMembersLimitAction::class)($user, $newInvites);
|
||||
}
|
||||
|
||||
public function canVisitShared(User $user): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
namespace App\Users\Restrictions\Engines;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use App\Users\Restrictions\RestrictionsEngine;
|
||||
|
||||
class MeteredBillingRestrictionsEngine implements RestrictionsEngine
|
||||
{
|
||||
public function canUpload(User $user, int $fileSize = 0): bool
|
||||
{
|
||||
// Disable upload when user has more than 3 failed payments
|
||||
return ! ($user->failedPayments()->count() >= 3);
|
||||
}
|
||||
|
||||
public function canDownload(User $user): bool
|
||||
{
|
||||
// Disable download when user has more than 3 failed payments
|
||||
return ! ($user->failedPayments()->count() >= 3);
|
||||
}
|
||||
|
||||
public function canCreateFolder(User $user): bool
|
||||
{
|
||||
// Disable create folder when user has more than 3 failed payments
|
||||
return ! ($user->failedPayments()->count() >= 3);
|
||||
}
|
||||
|
||||
public function canCreateTeamFolder(User $user): bool
|
||||
{
|
||||
// Disable create folder when user has more than 3 failed payments
|
||||
return ! ($user->failedPayments()->count() >= 3);
|
||||
}
|
||||
|
||||
public function canInviteTeamMembers(User $user, array $newInvites = []): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canVisitShared(User $user): bool
|
||||
{
|
||||
// Disable share visit when user has more than 3 failed payments
|
||||
return ! ($user->failedPayments()->count() >= 3);
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,11 @@ class RestrictionsManager extends Manager
|
||||
{
|
||||
public function getDefaultDriver(): string
|
||||
{
|
||||
return get_restriction_driver();
|
||||
return 'default';
|
||||
}
|
||||
|
||||
public function createDefaultDriver(): DefaultRestrictionsEngine
|
||||
{
|
||||
return new DefaultRestrictionsEngine();
|
||||
}
|
||||
|
||||
public function createFixedDriver(): FixedBillingRestrictionsEngine
|
||||
{
|
||||
return new FixedBillingRestrictionsEngine();
|
||||
}
|
||||
|
||||
public function createMeteredDriver(): MeteredBillingRestrictionsEngine
|
||||
{
|
||||
return new MeteredBillingRestrictionsEngine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Admin\Controllers\Dashboard;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use VueFileManager\Subscription\Domain\Transactions\Models\Transaction;
|
||||
use VueFileManager\Subscription\Domain\Transactions\Resources\TransactionCollection;
|
||||
|
||||
class GetLatestTransactionsController extends Controller
|
||||
{
|
||||
public function __invoke(): TransactionCollection
|
||||
{
|
||||
$transactions = Transaction::sortable([
|
||||
'created_at' => 'desc',
|
||||
])
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
return new TransactionCollection($transactions);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Files\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class RemoteUploadRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'urls.*' => 'required|url',
|
||||
'parent_id' => 'nullable|uuid',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Files\Requests;
|
||||
|
||||
use Domain\Admin\Rules\DisabledMimetypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UploadRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string',
|
||||
'parent_id' => 'nullable|uuid',
|
||||
'path' => 'sometimes|string',
|
||||
'is_last' => 'sometimes|string',
|
||||
'extension' => 'sometimes|string|nullable',
|
||||
'file' => ['required', 'file', new DisabledMimetypes],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Homepage\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Domain\Homepage\Mail\SendContactMessage;
|
||||
use Domain\Homepage\Requests\SendContactMessageRequest;
|
||||
|
||||
class SendContactMessageController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send contact message from homepage
|
||||
*/
|
||||
public function __invoke(
|
||||
SendContactMessageRequest $request
|
||||
): Response {
|
||||
// Abort in demo mode
|
||||
abort_if(is_demo(), 201, 'Done');
|
||||
|
||||
$contactEmail = get_settings('contact_email');
|
||||
|
||||
if ($contactEmail) {
|
||||
Mail::to($contactEmail)
|
||||
->send(new SendContactMessage($request->all()));
|
||||
}
|
||||
|
||||
return response('Done', 201);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Homepage\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendContactMessage extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public function __construct(
|
||||
private array $request
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*/
|
||||
public function build(): static
|
||||
{
|
||||
return $this->from(config('mail.from')['address'])
|
||||
->replyTo($this->request['email'])
|
||||
->subject('New Contact Message from ' . $this->request['email'])
|
||||
->view('mails.contact-message')
|
||||
->with('request', $this->request);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Homepage\Requests;
|
||||
|
||||
use App\Users\Rules\ReCaptchaRules;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rules\RequiredIf;
|
||||
|
||||
class SendContactMessageRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email',
|
||||
'message' => 'required|string',
|
||||
'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', 'nullable', app(ReCaptchaRules::class)],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Invoices\Controllers;
|
||||
|
||||
use Domain\Settings\Models\Setting;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use App\Users\Actions\FormatUsageEstimatesAction;
|
||||
use VueFileManager\Subscription\Domain\Transactions\Models\Transaction;
|
||||
|
||||
class GetInvoiceController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public FormatUsageEstimatesAction $formatUsageEstimates,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(Transaction $invoice): View|Factory|Application
|
||||
{
|
||||
// Get app settings
|
||||
$settings = json_decode(
|
||||
Setting::all()
|
||||
->pluck('value', 'name')
|
||||
);
|
||||
|
||||
// Format metadata
|
||||
if ($invoice->metadata) {
|
||||
$invoice->metadata = ($this->formatUsageEstimates)($invoice->currency, $invoice->metadata);
|
||||
}
|
||||
|
||||
// Return invoice view
|
||||
return view('vuefilemanager.invoice')
|
||||
->with('settings', $settings)
|
||||
->with('invoice', $invoice);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Notifications\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
|
||||
class FlushUserNotificationsController extends Controller
|
||||
{
|
||||
public function __invoke(): Response|Application|ResponseFactory
|
||||
{
|
||||
if (is_demo_account()) {
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
// Delete all notifications
|
||||
auth()->user()->notifications()->delete();
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Notifications\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Notifications\Resources\NotificationCollection;
|
||||
|
||||
class GetUserNotificationsController extends Controller
|
||||
{
|
||||
public function __invoke(): NotificationCollection
|
||||
{
|
||||
return new NotificationCollection(
|
||||
auth()->user()->notifications
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Notifications\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
|
||||
class MarkUserNotificationsAsReadController extends Controller
|
||||
{
|
||||
public function __invoke(): Response|Application|ResponseFactory
|
||||
{
|
||||
if (is_demo_account()) {
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
// Mark all notifications as read
|
||||
auth()->user()->unreadNotifications()->update(['read_at' => now()]);
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Notifications\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class NotificationCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = NotificationResource::class;
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Notifications\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class NotificationResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => $this->type,
|
||||
'attributes' => [
|
||||
'category' => $this->data['category'],
|
||||
'title' => $this->data['title'],
|
||||
'description' => $this->data['description'],
|
||||
'action' => $this->data['action'] ?? null,
|
||||
'created_at' => format_date($this->created_at, 'd. M. Y h:i'),
|
||||
'read_at' => $this->read_at ? format_date($this->read_at, 'd. M. Y h:i') : null,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Pages\Actions;
|
||||
|
||||
use Domain\Pages\Models\Page;
|
||||
|
||||
class SeedDefaultPagesAction
|
||||
{
|
||||
/**
|
||||
* Store default pages content like Terms of Service, Privacy Policy and Cookie Policy into database
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
collect(config('content.pages'))
|
||||
->each(fn ($page) => Page::updateOrCreate($page));
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Pages\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Domain\Pages\Models\Page;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Pages\Resources\PageResource;
|
||||
use Domain\Pages\Resources\PageCollection;
|
||||
|
||||
class AdminPagesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get all pages
|
||||
*/
|
||||
public function index(): PageCollection
|
||||
{
|
||||
return new PageCollection(
|
||||
Page::sortable()
|
||||
->paginate(10)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single page resource
|
||||
*/
|
||||
public function show(Page $page): PageResource
|
||||
{
|
||||
return new PageResource($page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update page content
|
||||
*/
|
||||
public function update(Request $request, Page $page): Response
|
||||
{
|
||||
// Abort in demo mode
|
||||
abort_if(is_demo(), 204, 'Done.');
|
||||
|
||||
$page->update(
|
||||
make_single_input($request)
|
||||
);
|
||||
|
||||
return response(
|
||||
new PageResource($page),
|
||||
204
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Pages\Controllers;
|
||||
|
||||
use Domain\Pages\Models\Page;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Pages\Resources\PageResource;
|
||||
|
||||
class PagesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get single page content
|
||||
*/
|
||||
public function show(Page $page): PageResource
|
||||
{
|
||||
return new PageResource($page);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Pages\Models;
|
||||
|
||||
use Kyslik\ColumnSortable\Sortable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @property string slug
|
||||
* @property string title
|
||||
* @property bool visibility
|
||||
* @property string content
|
||||
*/
|
||||
class Page extends Model
|
||||
{
|
||||
use Sortable, HasFactory;
|
||||
|
||||
public array $sortable = [
|
||||
'title',
|
||||
'slug',
|
||||
'visibility',
|
||||
];
|
||||
|
||||
public $fillable = [
|
||||
'slug',
|
||||
'title',
|
||||
'visibility',
|
||||
'content',
|
||||
];
|
||||
|
||||
protected $primaryKey = 'slug';
|
||||
|
||||
protected $keyType = 'string';
|
||||
|
||||
public $timestamps = false;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Pages\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PageCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PageResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Pages\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PageResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->slug,
|
||||
'type' => 'pages',
|
||||
'attributes' => [
|
||||
'visibility' => $this->visibility,
|
||||
'title' => $this->title,
|
||||
'slug' => $this->slug,
|
||||
'content' => $this->content,
|
||||
'content_formatted' => add_paragraphs($this->content),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\RemoteUpload\Actions;
|
||||
|
||||
use Log;
|
||||
use Error;
|
||||
use ErrorException;
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Domain\Files\Models\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Domain\Files\Resources\FileResource;
|
||||
use Domain\Files\Actions\ProcessFileAction;
|
||||
use Spatie\QueueableAction\QueueableAction;
|
||||
use Domain\Files\Actions\StoreExifDataAction;
|
||||
use Domain\Files\Actions\MoveFileToFTPStorageAction;
|
||||
use Domain\Files\Actions\ProcessImageThumbnailAction;
|
||||
use Domain\RemoteUpload\Events\RemoteFileCreatedEvent;
|
||||
use Domain\Files\Actions\MoveFileToExternalStorageAction;
|
||||
|
||||
class GetContentFromExternalSource
|
||||
{
|
||||
use QueueableAction;
|
||||
|
||||
public function __construct(
|
||||
public ProcessFileAction $processFile,
|
||||
public StoreExifDataAction $storeExifData,
|
||||
public MoveFileToFTPStorageAction $moveFileToFTPStorage,
|
||||
public ProcessImageThumbnailAction $createImageThumbnail,
|
||||
public MoveFileToExternalStorageAction $moveFileToExternalStorage,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
array $payload,
|
||||
User $user,
|
||||
) {
|
||||
$total = count($payload['urls']);
|
||||
$processed = 0;
|
||||
$failed = 0;
|
||||
|
||||
foreach ($payload['urls'] as $url) {
|
||||
try {
|
||||
// Get local disk instance
|
||||
$localDisk = Storage::disk('local');
|
||||
|
||||
// Get file from external source
|
||||
$response = Http::get($url);
|
||||
|
||||
// Get extension from response
|
||||
$extension = extractExtensionFromUrl($url, $response);
|
||||
|
||||
// Get blacklisted mimetypes
|
||||
$this->checkDisabledMimetypes($extension);
|
||||
|
||||
// Get file basename
|
||||
$basename = Str::uuid() . ".$extension";
|
||||
|
||||
// Get file name
|
||||
$name = array_key_exists('filename', pathinfo($url))
|
||||
? explode('?', pathinfo($url)['filename'])[0]
|
||||
: Str::uuid();
|
||||
|
||||
// Get file path
|
||||
$path = "files/$user->id/$basename";
|
||||
|
||||
// Store file to main storage disk
|
||||
$localDisk->put($path, $response->getBody());
|
||||
|
||||
// Create multiple image thumbnails
|
||||
($this->createImageThumbnail)($basename, $user->id);
|
||||
|
||||
// Store file exif information
|
||||
$exif = ($this->storeExifData)($path);
|
||||
|
||||
// Create new file
|
||||
$file = File::create([
|
||||
'mimetype' => $extension,
|
||||
'type' => getFileType($localDisk->mimeType($path)),
|
||||
'parent_id' => $payload['parent_id'] ?? null,
|
||||
'name' => $name ?? $basename,
|
||||
'basename' => $basename,
|
||||
'filesize' => $localDisk->size($path),
|
||||
'user_id' => $user->id,
|
||||
'creator_id' => auth()->id(),
|
||||
]);
|
||||
|
||||
// Attach file into the exif data
|
||||
$exif?->update(['file_id' => $file->id]);
|
||||
|
||||
// Move file to external storage
|
||||
match (config('filesystems.default')) {
|
||||
's3' => ($this->moveFileToExternalStorage)($basename, $user->id),
|
||||
'ftp', 'azure' => ($this->moveFileToFTPStorage)($basename, $user->id),
|
||||
default => null
|
||||
};
|
||||
|
||||
// Increment processed items count
|
||||
$processed++;
|
||||
|
||||
// Broadcast new file into the frontend
|
||||
RemoteFileCreatedEvent::dispatch([
|
||||
'progress' => [
|
||||
'total' => $total,
|
||||
'processed' => $processed,
|
||||
'failed' => $failed,
|
||||
],
|
||||
'file' => new FileResource($file),
|
||||
]);
|
||||
} catch (ErrorException | Error $e) {
|
||||
// Increment items count
|
||||
$processed++;
|
||||
$failed++;
|
||||
|
||||
// Broadcast new file into the frontend
|
||||
RemoteFileCreatedEvent::dispatch([
|
||||
'progress' => [
|
||||
'total' => $total,
|
||||
'processed' => $processed,
|
||||
'failed' => $failed,
|
||||
],
|
||||
'file' => null,
|
||||
]);
|
||||
|
||||
Log::error("Remote upload failed as {$e->getMessage()}");
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $extension
|
||||
*/
|
||||
protected function checkDisabledMimetypes(?string $extension): void
|
||||
{
|
||||
$mimetypeBlacklist = explode(',', get_settings('mimetypes_blacklist')) ?? null;
|
||||
|
||||
// If is extension in mimetype blacklist, Abort!
|
||||
if ($extension && array_intersect([str_replace('.', '', ".$extension")], $mimetypeBlacklist)) {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\RemoteUpload\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Sharing\Models\Share;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Files\Requests\RemoteUploadRequest;
|
||||
use Domain\RemoteUpload\Actions\GetContentFromExternalSource;
|
||||
|
||||
class RemoteUploadFileController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public GetContentFromExternalSource $getContentFromExternalSource,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(RemoteUploadRequest $request, ?Share $shared = null): Response|array
|
||||
{
|
||||
if (is_demo_account()) {
|
||||
return response('Files were successfully added to the upload queue', 201);
|
||||
}
|
||||
|
||||
// Get user
|
||||
$user = $request->filled('parent_id')
|
||||
? Folder::find($request->input('parent_id'))
|
||||
->getLatestParent()
|
||||
->user
|
||||
: auth()->user();
|
||||
|
||||
// Get content from external sources
|
||||
if (isBroadcasting()) {
|
||||
($this->getContentFromExternalSource)
|
||||
->onQueue()
|
||||
->execute($request->all(), $user);
|
||||
} else {
|
||||
($this->getContentFromExternalSource)($request->all(), $user);
|
||||
}
|
||||
|
||||
return response('Files were successfully added to the upload queue', 201);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\RemoteUpload\Controllers;
|
||||
|
||||
use DB;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Domain\Files\Requests\RemoteUploadRequest;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Domain\RemoteUpload\Actions\GetContentFromExternalSource;
|
||||
|
||||
class UploadFilesRemotelyForUploadRequestController
|
||||
{
|
||||
public function __construct(
|
||||
private GetContentFromExternalSource $getContentFromExternalSource,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function __invoke(RemoteUploadRequest $request, UploadRequest $uploadRequest)
|
||||
{
|
||||
// Get upload request root folder query
|
||||
$folder = Folder::where('id', $uploadRequest->id);
|
||||
|
||||
// Create folder if not exist
|
||||
if ($folder->doesntExist()) {
|
||||
$this->createFolder($uploadRequest);
|
||||
}
|
||||
|
||||
// Set default parent_id for uploaded file
|
||||
if (is_null($request->input('parent_id'))) {
|
||||
$request->merge(['parent_id' => $uploadRequest->id]);
|
||||
}
|
||||
|
||||
// Get content from external sources
|
||||
if (isBroadcasting()) {
|
||||
($this->getContentFromExternalSource)
|
||||
->onQueue()
|
||||
->execute($request->all(), $uploadRequest->user);
|
||||
} else {
|
||||
($this->getContentFromExternalSource)($request->all(), $uploadRequest->user);
|
||||
}
|
||||
|
||||
// Set timestamp for auto filling
|
||||
cache()->set("auto-filling.$uploadRequest->id", now()->toString());
|
||||
|
||||
return response('Files were successfully added to the upload queue', 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create root Upload Request folder
|
||||
*/
|
||||
private function createFolder(UploadRequest $uploadRequest): void
|
||||
{
|
||||
// Format timestamp
|
||||
$timestamp = format_date($uploadRequest->created_at, 'd. M. Y');
|
||||
|
||||
// Create folder
|
||||
DB::table('folders')->insert([
|
||||
'id' => $uploadRequest->id,
|
||||
'parent_id' => $uploadRequest->folder_id ?? null,
|
||||
'user_id' => $uploadRequest->user_id,
|
||||
'name' => $uploadRequest->name ?? __t('upload_request_default_folder', ['timestamp' => $timestamp]),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
// Update upload request status
|
||||
$uploadRequest->update([
|
||||
'status' => 'filling',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\RemoteUpload\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Sharing\Models\Share;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Files\Requests\RemoteUploadRequest;
|
||||
use Domain\Sharing\Actions\ProtectShareRecordAction;
|
||||
use Domain\Sharing\Actions\VerifyAccessToItemAction;
|
||||
use Domain\RemoteUpload\Actions\GetContentFromExternalSource;
|
||||
|
||||
class VisitorRemoteUploadFileController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public ProtectShareRecordAction $protectShareRecord,
|
||||
public VerifyAccessToItemAction $verifyAccessToItem,
|
||||
public GetContentFromExternalSource $getContentFromExternalSource,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(RemoteUploadRequest $request, ?Share $shared = null): Response|array
|
||||
{
|
||||
// Check ability to access protected share record
|
||||
($this->protectShareRecord)($shared);
|
||||
|
||||
// Check shared permission
|
||||
if (is_visitor($shared)) {
|
||||
abort(403, "You don't have access to this item");
|
||||
}
|
||||
|
||||
// Check access to requested directory
|
||||
($this->verifyAccessToItem)($request->input('parent_id'), $shared);
|
||||
|
||||
// Get content from external sources
|
||||
if (isBroadcasting()) {
|
||||
($this->getContentFromExternalSource)
|
||||
->onQueue()
|
||||
->execute($request->all(), $shared->user);
|
||||
} else {
|
||||
($this->getContentFromExternalSource)($request->all(), $shared->user);
|
||||
}
|
||||
|
||||
return response('Files were successfully added to the upload queue', 201);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\RemoteUpload\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
|
||||
|
||||
class RemoteFileCreatedEvent implements ShouldBroadcastNow
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public array $payload,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The event's broadcast name.
|
||||
*/
|
||||
public function broadcastAs(): string
|
||||
{
|
||||
return 'RemoteFile.Created';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*/
|
||||
public function broadcastOn(): PrivateChannel
|
||||
{
|
||||
return new PrivateChannel("App.Users.Models.User.{$this->payload['file']->user_id}");
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Controllers;
|
||||
|
||||
use Artisan;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Settings\Requests\StoreBroadcastServiceCredentialsRequest;
|
||||
|
||||
class StoreBroadcastServiceCredentialsController
|
||||
{
|
||||
/**
|
||||
* Configure stripe additionally
|
||||
*/
|
||||
public function __invoke(StoreBroadcastServiceCredentialsRequest $request): Response
|
||||
{
|
||||
// Abort in demo mode
|
||||
abort_if(is_demo(), 204, 'Done.');
|
||||
|
||||
// Get and store credentials
|
||||
if (! app()->runningUnitTests()) {
|
||||
$credentials = [
|
||||
'pusher' => [
|
||||
'BROADCAST_DRIVER' => 'pusher',
|
||||
'PUSHER_APP_ID' => $request->input('id'),
|
||||
'PUSHER_APP_KEY' => $request->input('key'),
|
||||
'PUSHER_APP_SECRET' => $request->input('secret'),
|
||||
'PUSHER_APP_CLUSTER' => $request->input('cluster'),
|
||||
'PUSHER_APP_HOST' => '',
|
||||
'PUSHER_APP_PORT' => '',
|
||||
'PUSHER_APP_TLS' => true,
|
||||
],
|
||||
'native' => [
|
||||
'BROADCAST_DRIVER' => 'pusher',
|
||||
'PUSHER_APP_ID' => 'local',
|
||||
'PUSHER_APP_KEY' => 'local',
|
||||
'PUSHER_APP_SECRET' => 'local',
|
||||
'PUSHER_APP_CLUSTER' => 'local',
|
||||
'PUSHER_APP_HOST' => $request->input('host'),
|
||||
'PUSHER_APP_PORT' => '',
|
||||
'PUSHER_APP_TLS' => $request->boolean('tls') ? 'true' : 'false',
|
||||
],
|
||||
'none' => [
|
||||
'BROADCAST_DRIVER' => 'null',
|
||||
],
|
||||
];
|
||||
|
||||
// Store credentials into the .env file
|
||||
setEnvironmentValue($credentials[$request->input('driver')]);
|
||||
|
||||
// Clear cache
|
||||
if (! is_dev()) {
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
}
|
||||
}
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Controllers;
|
||||
|
||||
use Artisan;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Settings\Models\Setting;
|
||||
use Domain\Settings\Requests\StorePaymentServiceCredentialsRequest;
|
||||
|
||||
class StorePaymentServiceCredentialsController
|
||||
{
|
||||
/**
|
||||
* Configure stripe additionally
|
||||
*/
|
||||
public function __invoke(StorePaymentServiceCredentialsRequest $request): Response
|
||||
{
|
||||
// Abort in demo mode
|
||||
abort_if(is_demo(), 204, 'Done.');
|
||||
|
||||
$options = [
|
||||
'stripe' => [
|
||||
'name' => 'allowed_stripe',
|
||||
'value' => 1,
|
||||
],
|
||||
'paypal' => [
|
||||
'name' => 'allowed_paypal',
|
||||
'value' => 1,
|
||||
],
|
||||
'paystack' => [
|
||||
'name' => 'allowed_paystack',
|
||||
'value' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
// Get options
|
||||
collect([$options[$request->input('service')]])
|
||||
->each(fn ($setting) => Setting::updateOrCreate([
|
||||
'name' => $setting['name'],
|
||||
], [
|
||||
'value' => $setting['value'],
|
||||
]));
|
||||
|
||||
$PayPalDefaultMode = config('subscription.credentials.paypal.is_live') ? 'true' : 'false';
|
||||
|
||||
// Get and store credentials
|
||||
if (! app()->runningUnitTests()) {
|
||||
$credentials = [
|
||||
'stripe' => [
|
||||
'STRIPE_PUBLIC_KEY' => $request->input('key'),
|
||||
'STRIPE_SECRET_KEY' => $request->input('secret'),
|
||||
'STRIPE_WEBHOOK_SECRET' => $request->input('webhook'),
|
||||
],
|
||||
'paystack' => [
|
||||
'PAYSTACK_PUBLIC_KEY' => $request->input('key'),
|
||||
'PAYSTACK_SECRET' => $request->input('secret'),
|
||||
],
|
||||
'paypal' => [
|
||||
'PAYPAL_CLIENT_ID' => $request->input('key'),
|
||||
'PAYPAL_CLIENT_SECRET' => $request->input('secret'),
|
||||
'PAYPAL_WEBHOOK_ID' => $request->input('webhook'),
|
||||
'PAYPAL_IS_LIVE' => $request->has('live') ? (string) $request->input('live') : $PayPalDefaultMode,
|
||||
],
|
||||
];
|
||||
|
||||
// Store credentials into the .env file
|
||||
setEnvironmentValue($credentials[$request->input('service')]);
|
||||
|
||||
// Call plan synchronization for makingcg/subscription package
|
||||
cache()->add('action.synchronize-plans', now()->toString());
|
||||
|
||||
// Clear cache
|
||||
if (! is_dev()) {
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
}
|
||||
}
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Controllers;
|
||||
|
||||
use Artisan;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Settings\Models\Setting;
|
||||
use Domain\Settings\Requests\StoreSocialServiceCredentialsRequest;
|
||||
|
||||
class StoreSocialServiceCredentialsController
|
||||
{
|
||||
/**
|
||||
* Configure stripe additionally
|
||||
*/
|
||||
public function __invoke(StoreSocialServiceCredentialsRequest $request): Response
|
||||
{
|
||||
// Abort in demo mode
|
||||
abort_if(is_demo(), 204, 'Done.');
|
||||
|
||||
// Set on social login
|
||||
Setting::updateOrCreate([
|
||||
'name' => "allowed_{$request->input('service')}",
|
||||
], [
|
||||
'value' => 1,
|
||||
]);
|
||||
|
||||
// Get and store credentials
|
||||
if (! app()->runningUnitTests()) {
|
||||
$credentials = [
|
||||
'facebook' => [
|
||||
'FACEBOOK_CLIENT_ID' => $request->input('client_id'),
|
||||
'FACEBOOK_CLIENT_SECRET' => $request->input('client_secret'),
|
||||
],
|
||||
'google' => [
|
||||
'GOOGLE_CLIENT_ID' => $request->input('client_id'),
|
||||
'GOOGLE_CLIENT_SECRET' => $request->input('client_secret'),
|
||||
],
|
||||
'github' => [
|
||||
'GITHUB_CLIENT_ID' => $request->input('client_id'),
|
||||
'GITHUB_CLIENT_SECRET' => $request->input('client_secret'),
|
||||
],
|
||||
'recaptcha' => [
|
||||
'RECAPTCHA_CLIENT_ID' => $request->input('client_id'),
|
||||
'RECAPTCHA_CLIENT_SECRET' => $request->input('client_secret'),
|
||||
],
|
||||
];
|
||||
|
||||
// Store credentials into the .env file
|
||||
setEnvironmentValue($credentials[$request->input('service')]);
|
||||
|
||||
// Clear cache
|
||||
if (! is_dev()) {
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
}
|
||||
}
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreBroadcastServiceCredentialsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'driver' => 'required|string',
|
||||
'id' => 'sometimes|nullable|string',
|
||||
'key' => 'sometimes|nullable|string',
|
||||
'secret' => 'sometimes|nullable|string',
|
||||
'cluster' => 'sometimes|nullable|string',
|
||||
'port' => 'sometimes|nullable|string',
|
||||
'host' => 'sometimes|nullable|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StorePaymentServiceCredentialsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'key' => 'required|string',
|
||||
'secret' => 'required|string',
|
||||
'webhook' => 'sometimes|string',
|
||||
'live' => 'sometimes|nullable|boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreSocialServiceCredentialsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'client_id' => 'required|string',
|
||||
'client_secret' => 'required|string',
|
||||
'service' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Settings\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpgradeLicenseRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'purchaseCode' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\SetupWizard\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripeBillingRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'billing_phone_number' => 'sometimes|nullable|string',
|
||||
'billing_postal_code' => 'required|string',
|
||||
'billing_vat_number' => 'required|string',
|
||||
'billing_address' => 'required|string',
|
||||
'billing_country' => 'required|string',
|
||||
'billing_state' => 'required|string',
|
||||
'billing_city' => 'required|string',
|
||||
'billing_name' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\SetupWizard\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripeCredentialsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'currency' => 'required|string',
|
||||
'webhookSecret' => 'required|string',
|
||||
'secret' => 'required|string',
|
||||
'key' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\SetupWizard\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripePlansRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'plans' => 'required|array',
|
||||
'plans.*.type' => 'required|string',
|
||||
'plans.*.attributes.name' => 'required|string',
|
||||
'plans.*.attributes.price' => 'required|string',
|
||||
'plans.*.attributes.description' => 'sometimes|nullable|string',
|
||||
'plans.*.attributes.capacity' => 'required|digits_between:1,9',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class BillingAlertTriggeredNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ['mail', 'database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('billing_alert_reached_long'))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('billing_alert_reached_long_note'))
|
||||
->action(__t('show_billing'), url('/user/settings/billing'));
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'category' => 'billing-alert',
|
||||
'title' => __t('billing_alert_reached_short'),
|
||||
'description' => __t('billing_alert_reached_short_note'),
|
||||
'action' => [
|
||||
'type' => 'route',
|
||||
'params' => [
|
||||
'route' => __t('billing'),
|
||||
'button' => __t('show_billing'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class BonusCreditAddedNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public string $bonus
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*/
|
||||
public function via(mixed $notifiable): array
|
||||
{
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*/
|
||||
public function toArray(mixed $notifiable): array
|
||||
{
|
||||
return [
|
||||
'category' => 'gift',
|
||||
'title' => __t('you_received_bonus', ['bonus' => $this->bonus]),
|
||||
'description' => __t('you_received_bonus_note', ['bonus' => $this->bonus]),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class ChargeFromCreditCardFailedAgainNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('charge_from_card_failed_again_subject'))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('charge_from_card_failed_again_line'))
|
||||
->action(__t('charge_from_card_failed_again_action'), url('/user/settings/billing'));
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class ChargeFromCreditCardFailedNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('charge_from_card_failed_subject'))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('charge_from_card_failed_line'))
|
||||
->action(__t('charge_from_card_failed_action'), url('/user/settings/billing'));
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class ConfirmStripePaymentNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function __construct(
|
||||
public array $payload
|
||||
) {
|
||||
}
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('confirm_payment'))
|
||||
->greeting(__t('confirm_payment_greeting', ['amount' => $this->payload['amount']]))
|
||||
->line(__t('confirm_payment_line'))
|
||||
->action(__t('confirm_payment_action'), $this->payload['url']);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class InsufficientBalanceNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ['mail', 'database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('withdrawal_failed_long'))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('withdrawal_failed_long_note'))
|
||||
->action(__t('fund_your_account'), url('/user/settings/billing'));
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'category' => 'insufficient-balance',
|
||||
'title' => __t('withdrawal_failed_short'),
|
||||
'description' => __t('withdrawal_failed_short_note'),
|
||||
'action' => [
|
||||
'type' => 'route',
|
||||
'params' => [
|
||||
'route' => __t('billing'),
|
||||
'button' => __t('show_billing'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Subscriptions\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use VueFileManager\Subscription\Domain\Subscriptions\Models\Subscription;
|
||||
|
||||
class SubscriptionWasCreatedNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function __construct(
|
||||
public Subscription $subscription,
|
||||
) {
|
||||
}
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('subscription_created_long', ['plan' => $this->subscription->plan->name]))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('subscription_created_long_note', ['plan' => $this->subscription->plan->name]))
|
||||
->action(__t('go_to_subscription'), url('/user/settings/billing'));
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'category' => 'subscription-created',
|
||||
'title' => __t('subscription_created_short'),
|
||||
'description' => __t('subscription_created_short_note', ['plan' => $this->subscription->plan->name]),
|
||||
'action' => [
|
||||
'type' => 'route',
|
||||
'params' => [
|
||||
'route' => __t('billing'),
|
||||
'button' => __t('show_billing'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use App\Users\Models\User;
|
||||
|
||||
class CheckMaxTeamMembersLimitAction
|
||||
{
|
||||
public function __invoke(User $user, array $newInvites): bool
|
||||
{
|
||||
// Get user limitation summary
|
||||
$limits = $user->limitations->summary();
|
||||
|
||||
// Check unlimited option
|
||||
if ((int) $limits['max_team_members']['total'] === -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get currently used member emails
|
||||
$allowedEmails = $limits['max_team_members']['meta']['allowed_emails'];
|
||||
|
||||
// Get new email invites from request
|
||||
$invitationEmails = collect($newInvites)
|
||||
->pluck('email');
|
||||
|
||||
// Count total unique members
|
||||
$totalMembers = $allowedEmails
|
||||
->merge($invitationEmails)
|
||||
->unique()
|
||||
->count();
|
||||
|
||||
// Check if there is more unique members than total max team members are allowed
|
||||
return ! ($totalMembers > $limits['max_team_members']['total']);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use DB;
|
||||
use App\Users\Models\User;
|
||||
use Domain\Teams\Models\TeamFolderInvitation;
|
||||
|
||||
class ClearActionInInvitationNotificationAction
|
||||
{
|
||||
public function __invoke(User $user, TeamFolderInvitation $invitation): void
|
||||
{
|
||||
if (is_demo_account()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get notification with invitation
|
||||
$notification = DB::table('notifications')
|
||||
->where('notifiable_id', $user->id)
|
||||
->where('data', 'LIKE', "%{$invitation->id}%")
|
||||
->first();
|
||||
|
||||
if ($notification) {
|
||||
// Get data
|
||||
$data = json_decode($notification->data);
|
||||
|
||||
// Clear action object
|
||||
$data->action = null;
|
||||
|
||||
// Update notification
|
||||
DB::table('notifications')
|
||||
->where('notifiable_id', $user->id)
|
||||
->where('data', 'LIKE', "%{$invitation->id}%")
|
||||
->update([
|
||||
'data' => json_encode($data),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Spatie\QueueableAction\QueueableAction;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Domain\Teams\Models\TeamFolderInvitation;
|
||||
use Domain\Teams\Notifications\InvitationIntoTeamFolder;
|
||||
|
||||
class InviteMembersIntoTeamFolderAction
|
||||
{
|
||||
use QueueableAction;
|
||||
|
||||
public function __invoke(
|
||||
array $members,
|
||||
Folder $folder,
|
||||
): void {
|
||||
collect($members)
|
||||
->each(function ($member) use ($folder) {
|
||||
// Create invitation
|
||||
$invitation = TeamFolderInvitation::create([
|
||||
'permission' => $member['permission'],
|
||||
'email' => $member['email'],
|
||||
'parent_id' => $folder->id,
|
||||
'inviter_id' => $folder->user_id,
|
||||
]);
|
||||
|
||||
// Get user
|
||||
$user = User::where('email', $member['email'])->first();
|
||||
|
||||
// Invite native user
|
||||
if ($user) {
|
||||
$user->notify(new InvitationIntoTeamFolder($folder, $invitation));
|
||||
}
|
||||
|
||||
// Invite guest
|
||||
if (! $user) {
|
||||
Notification::route('mail', $member['email'])
|
||||
->notify(new InvitationIntoTeamFolder($folder, $invitation));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class SetTeamFolderPropertyForAllChildrenAction
|
||||
{
|
||||
public function __invoke(Folder $folder, bool $isTeamFolder)
|
||||
{
|
||||
// Get all children of team folder
|
||||
$childrenFolderIds = Folder::with('folders:id,parent_id')
|
||||
->where('id', $folder->id)
|
||||
->get('id');
|
||||
|
||||
// Set all children as team_folder = true
|
||||
DB::table('folders')
|
||||
->whereIn('id', Arr::flatten(filter_folders_ids($childrenFolderIds)))
|
||||
->update(['team_folder' => $isTeamFolder]);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UpdateInvitationsAction
|
||||
{
|
||||
public function __construct(
|
||||
public InviteMembersIntoTeamFolderAction $inviteMembers,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(Folder $folder, $invitations): void
|
||||
{
|
||||
// Get stored invitations from team folder
|
||||
$storedInvitations = $folder
|
||||
->teamInvitations()
|
||||
->pluck('email');
|
||||
|
||||
// Get newbies added by user in request
|
||||
$newbies = collect($invitations)
|
||||
->filter(
|
||||
fn ($invitation) => ! in_array($invitation['email'], $storedInvitations->toArray())
|
||||
);
|
||||
|
||||
// Get deleted invitations by user in request
|
||||
$removed = $storedInvitations->diff(
|
||||
collect($invitations)->pluck('email')->toArray()
|
||||
);
|
||||
|
||||
// Invite team members
|
||||
if ($newbies->isNotEmpty()) {
|
||||
$this->inviteMembers->onQueue()->execute($newbies->toArray(), $folder);
|
||||
}
|
||||
|
||||
// Delete invite from team folder
|
||||
if ($removed->isNotEmpty()) {
|
||||
DB::table('team_folder_invitations')
|
||||
->where('parent_id', $folder->id)
|
||||
->whereIn('email', $removed)
|
||||
->delete();
|
||||
}
|
||||
|
||||
// Update privileges
|
||||
collect($invitations)
|
||||
->each(
|
||||
fn ($invitation) =>
|
||||
DB::table('team_folder_invitations')
|
||||
->where('parent_id', $folder->id)
|
||||
->where('email', $invitation['email'])
|
||||
->update([
|
||||
'permission' => $invitation['permission'],
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use DB;
|
||||
use Domain\Folders\Models\Folder;
|
||||
|
||||
class UpdateMembersAction
|
||||
{
|
||||
public function __invoke(Folder $folder, $members): void
|
||||
{
|
||||
$existingMembers = $folder
|
||||
->teamMembers()
|
||||
->pluck('user_id');
|
||||
|
||||
// Get deleted members from request
|
||||
$deletedMembers = $existingMembers->diff(
|
||||
collect($members)->pluck('id')->toArray()
|
||||
);
|
||||
|
||||
// Remove team members from team folder
|
||||
if ($deletedMembers->isNotEmpty()) {
|
||||
DB::table('team_folder_members')
|
||||
->where('parent_id', $folder->id)
|
||||
->whereIn('user_id', $deletedMembers->toArray())
|
||||
->delete();
|
||||
}
|
||||
|
||||
// Update privileges
|
||||
collect($members)
|
||||
->each(
|
||||
fn ($member) =>
|
||||
DB::table('team_folder_members')
|
||||
->where('parent_id', $folder->id)
|
||||
->where('user_id', $member['id'])
|
||||
->update([
|
||||
'permission' => $member['permission'],
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use Str;
|
||||
use Gate;
|
||||
use Domain\Files\Models\File;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Domain\Files\Resources\FilesCollection;
|
||||
use Domain\Folders\Resources\FolderResource;
|
||||
use Domain\Folders\Resources\FolderCollection;
|
||||
|
||||
class BrowseSharedWithMeController
|
||||
{
|
||||
public function __invoke($id): array
|
||||
{
|
||||
$id = Str::isUuid($id) ? $id : null;
|
||||
|
||||
if ($id) {
|
||||
$teamFolder = Folder::findOrFail($id)->getLatestParent();
|
||||
|
||||
if (! Gate::any(['can-edit', 'can-view'], [$teamFolder, null])) {
|
||||
abort(403, 'Access Denied');
|
||||
}
|
||||
|
||||
$folders = Folder::with(['parent:id,name'])
|
||||
->where('parent_id', $id)
|
||||
->sortable()
|
||||
->get();
|
||||
|
||||
$files = File::with(['parent:id,name'])
|
||||
->where('parent_id', $id)
|
||||
->sortable()
|
||||
->get();
|
||||
}
|
||||
|
||||
if (! $id) {
|
||||
$sharedFolderIds = DB::table('team_folder_members')
|
||||
->where('user_id', Auth::id())
|
||||
->whereIn('permission', ['can-edit', 'can-view'])
|
||||
->pluck('parent_id');
|
||||
|
||||
$folders = Folder::whereIn('id', $sharedFolderIds)
|
||||
->sortable()
|
||||
->get();
|
||||
}
|
||||
|
||||
return [
|
||||
'root' => $id ? new FolderResource(Folder::findOrFail($id)) : null,
|
||||
'folders' => new FolderCollection($folders),
|
||||
'files' => isset($files) ? new FilesCollection($files) : new FilesCollection([]),
|
||||
'teamFolder' => $id ? new FolderResource($teamFolder) : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Teams\Models\TeamFolderMember;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Domain\Teams\Requests\ConvertIntoTeamFolderRequest;
|
||||
use Domain\Teams\Actions\InviteMembersIntoTeamFolderAction;
|
||||
use Domain\Teams\Actions\SetTeamFolderPropertyForAllChildrenAction;
|
||||
|
||||
class ConvertFolderIntoTeamFolderController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public InviteMembersIntoTeamFolderAction $inviteMembers,
|
||||
public SetTeamFolderPropertyForAllChildrenAction $setTeamFolderPropertyForAllChildren,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ConvertIntoTeamFolderRequest $request,
|
||||
Folder $folder
|
||||
): ResponseFactory|Response {
|
||||
// Abort in demo mode
|
||||
if (is_demo_account()) {
|
||||
return response($folder, 201);
|
||||
}
|
||||
|
||||
// Check if user didn't exceed max team members limit
|
||||
if (! $folder->user->canInviteTeamMembers($request->input('invitations'))) {
|
||||
return response([
|
||||
'type' => 'error',
|
||||
'message' => 'You exceed your members limit.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Update root team folder
|
||||
$folder->update([
|
||||
'team_folder' => 1,
|
||||
'parent_id' => null,
|
||||
]);
|
||||
|
||||
// Mark all children folders as team folder
|
||||
($this->setTeamFolderPropertyForAllChildren)($folder, true);
|
||||
|
||||
// Attach owner into members
|
||||
TeamFolderMember::create([
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $folder->user_id,
|
||||
'permission' => 'owner',
|
||||
]);
|
||||
|
||||
// Invite team members
|
||||
($this->inviteMembers)($request->input('invitations'), $folder);
|
||||
|
||||
return response($folder, 201);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Teams\Models\TeamFolderMember;
|
||||
use Domain\Teams\Models\TeamFolderInvitation;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Domain\Teams\Resources\TeamInvitationResource;
|
||||
use Domain\Teams\Actions\ClearActionInInvitationNotificationAction;
|
||||
|
||||
class InvitationsController extends Controller
|
||||
{
|
||||
public function show(TeamFolderInvitation $invitation)
|
||||
{
|
||||
if ($invitation->status !== 'pending') {
|
||||
abort(410);
|
||||
}
|
||||
|
||||
return new TeamInvitationResource($invitation);
|
||||
}
|
||||
|
||||
public function update(
|
||||
TeamFolderInvitation $invitation,
|
||||
ClearActionInInvitationNotificationAction $clearActionInInvitationNotification,
|
||||
): ResponseFactory|Response {
|
||||
$user = User::where('email', $invitation->email)
|
||||
->first();
|
||||
|
||||
if ($user) {
|
||||
if (is_demo_account()) {
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
$invitation->accept();
|
||||
|
||||
// Store team member
|
||||
TeamFolderMember::create([
|
||||
'user_id' => $user->id,
|
||||
'parent_id' => $invitation->parent_id,
|
||||
'permission' => $invitation->permission,
|
||||
]);
|
||||
|
||||
// Clear action in existing notification
|
||||
$clearActionInInvitationNotification($user, $invitation);
|
||||
}
|
||||
|
||||
if (! $user) {
|
||||
$invitation->update([
|
||||
'status' => 'waiting-for-registration',
|
||||
]);
|
||||
}
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
public function destroy(
|
||||
TeamFolderInvitation $invitation,
|
||||
ClearActionInInvitationNotificationAction $clearActionInInvitationNotification,
|
||||
): ResponseFactory|Response {
|
||||
$invitation->reject();
|
||||
|
||||
// Get user from invitation
|
||||
$user = User::where('email', $invitation->email)
|
||||
->first();
|
||||
|
||||
// Clear action in existing notification
|
||||
if ($user) {
|
||||
if (is_demo_account()) {
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
$clearActionInInvitationNotification($user, $invitation);
|
||||
}
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use Gate;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
|
||||
class LeaveTeamFolderController extends Controller
|
||||
{
|
||||
public function __invoke(Folder $folder): Response|Application|ResponseFactory
|
||||
{
|
||||
// Abort in demo mode
|
||||
if (is_demo_account()) {
|
||||
return response('Done.', 204);
|
||||
}
|
||||
|
||||
// Authorize action
|
||||
if (! Gate::any(['can-edit', 'can-view'], [$folder, null])) {
|
||||
abort(403, 'Access Denied');
|
||||
}
|
||||
|
||||
// Find and delete attached member from team folder
|
||||
DB::table('team_folder_members')
|
||||
->where('parent_id', $folder->id)
|
||||
->where('user_id', auth()->id())
|
||||
->delete();
|
||||
|
||||
return response('Done.', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use Gate;
|
||||
use Domain\Folders\Models\Folder;
|
||||
|
||||
class NavigationTreeController
|
||||
{
|
||||
public function __invoke(Folder $folder): array
|
||||
{
|
||||
$teamFolder = $folder->getLatestParent();
|
||||
|
||||
if (! Gate::any(['can-edit', 'can-view'], [$teamFolder, null])) {
|
||||
abort(403, 'Access Denied');
|
||||
}
|
||||
|
||||
$folders = Folder::with('folders:id,parent_id,id,name,team_folder')
|
||||
->where('parent_id', $teamFolder->id)
|
||||
->sortable()
|
||||
->get(['id', 'parent_id', 'id', 'name', 'team_folder']);
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => $teamFolder->name,
|
||||
'folders' => $folders,
|
||||
'isMovable' => true,
|
||||
'isOpen' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Domain\Files\Models\File;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Domain\Teams\Models\TeamFolderMember;
|
||||
use Domain\Teams\DTO\CreateTeamFolderData;
|
||||
use Domain\Files\Resources\FilesCollection;
|
||||
use Domain\Folders\Resources\FolderResource;
|
||||
use Domain\Teams\Actions\UpdateMembersAction;
|
||||
use Domain\Folders\Resources\FolderCollection;
|
||||
use Domain\Teams\Actions\UpdateInvitationsAction;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Domain\Teams\Requests\CreateTeamFolderRequest;
|
||||
use Domain\Teams\Requests\UpdateTeamFolderMembersRequest;
|
||||
use Domain\Teams\Actions\InviteMembersIntoTeamFolderAction;
|
||||
use Domain\Teams\Actions\SetTeamFolderPropertyForAllChildrenAction;
|
||||
|
||||
class TeamFoldersController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public InviteMembersIntoTeamFolderAction $inviteMembers,
|
||||
public SetTeamFolderPropertyForAllChildrenAction $setTeamFolderPropertyForAllChildren,
|
||||
) {
|
||||
}
|
||||
|
||||
public function show($id): array
|
||||
{
|
||||
$id = Str::isUuid($id) ? $id : null;
|
||||
|
||||
if ($id) {
|
||||
$folders = Folder::where('parent_id', $id)
|
||||
->where('team_folder', true)
|
||||
->sortable()
|
||||
->get();
|
||||
|
||||
$files = File::where('parent_id', $id)
|
||||
->sortable()
|
||||
->get();
|
||||
}
|
||||
|
||||
if (! $id) {
|
||||
$folders = Folder::where('parent_id', null)
|
||||
->where('team_folder', true)
|
||||
->where('user_id', Auth::id())
|
||||
->sortable()
|
||||
->get();
|
||||
}
|
||||
|
||||
// Collect folders and files to single array
|
||||
return [
|
||||
'folders' => new FolderCollection($folders),
|
||||
'files' => isset($files) ? new FilesCollection($files) : new FilesCollection([]),
|
||||
'root' => $id ? new FolderResource(Folder::findOrFail($id)) : null,
|
||||
'teamFolder' => $id ? new FolderResource(Folder::findOrFail($id)->getLatestParent()) : null,
|
||||
];
|
||||
}
|
||||
|
||||
public function store(
|
||||
CreateTeamFolderRequest $request,
|
||||
): ResponseFactory | Response {
|
||||
// Abort in demo mode
|
||||
abort_if(is_demo_account(), 201, 'Done.');
|
||||
|
||||
$data = CreateTeamFolderData::fromRequest($request);
|
||||
|
||||
// Check if user can create team folder
|
||||
if (! $request->user()->canCreateTeamFolder()) {
|
||||
return response([
|
||||
'type' => 'error',
|
||||
'message' => 'This user action is not allowed.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Check if user didn't exceed max team members limit
|
||||
if (! $request->user()->canInviteTeamMembers($data->invitations)) {
|
||||
return response([
|
||||
'type' => 'error',
|
||||
'message' => 'You exceed your members limit.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Create folder
|
||||
$folder = Folder::create([
|
||||
'user_id' => $request->user()->id,
|
||||
'name' => $data->name,
|
||||
'team_folder' => 1,
|
||||
]);
|
||||
|
||||
// Attach owner into members
|
||||
TeamFolderMember::create([
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $request->user()->id,
|
||||
'permission' => 'owner',
|
||||
]);
|
||||
|
||||
// Invite team members
|
||||
$this->inviteMembers->onQueue()->execute($data->invitations, $folder);
|
||||
|
||||
return response(new FolderResource($folder), 201);
|
||||
}
|
||||
|
||||
public function update(
|
||||
UpdateTeamFolderMembersRequest $request,
|
||||
Folder $folder,
|
||||
UpdateInvitationsAction $updateInvitations,
|
||||
UpdateMembersAction $updateMembers,
|
||||
): ResponseFactory | Response {
|
||||
// Abort in demo mode
|
||||
if (is_demo_account()) {
|
||||
return response(new FolderResource($folder), 201);
|
||||
}
|
||||
|
||||
// Authorize request
|
||||
$this->authorize('owner', $folder);
|
||||
|
||||
// Check if user didn't exceed max team members limit
|
||||
if (! $request->user()->canInviteTeamMembers($request->input('invitations'))) {
|
||||
return response([
|
||||
'type' => 'error',
|
||||
'message' => 'You exceed your members limit.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
$updateInvitations(
|
||||
$folder,
|
||||
$request->input('invitations')
|
||||
);
|
||||
|
||||
$updateMembers(
|
||||
$folder,
|
||||
$request->input('members')
|
||||
);
|
||||
|
||||
return response(new FolderResource($folder), 201);
|
||||
}
|
||||
|
||||
public function destroy(Folder $folder): ResponseFactory | Response
|
||||
{
|
||||
// Abort in demo mode
|
||||
if (is_demo_account()) {
|
||||
return response('Done.', 201);
|
||||
}
|
||||
|
||||
$this->authorize('owner', $folder);
|
||||
|
||||
// Delete existing invitations
|
||||
DB::table('team_folder_invitations')
|
||||
->where('parent_id', $folder->id)
|
||||
->delete();
|
||||
|
||||
// Delete attached members from folder
|
||||
DB::table('team_folder_members')
|
||||
->where('parent_id', $folder->id)
|
||||
->delete();
|
||||
|
||||
($this->setTeamFolderPropertyForAllChildren)($folder, false);
|
||||
|
||||
$folder->update([
|
||||
'team_folder' => 0,
|
||||
]);
|
||||
|
||||
return response('Done.', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\DTO;
|
||||
|
||||
use Spatie\DataTransferObject\DataTransferObject;
|
||||
|
||||
class CreateTeamFolderData extends DataTransferObject
|
||||
{
|
||||
public string $name;
|
||||
public array $invitations;
|
||||
|
||||
public static function fromRequest($request): self
|
||||
{
|
||||
return new self([
|
||||
'name' => $request->input('name'),
|
||||
'invitations' => $request->input('invitations'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Models;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Database\Factories\TeamFolderInvitationFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @method static create(array $array)
|
||||
* @property string id
|
||||
* @property string parent_id
|
||||
* @property string email
|
||||
* @property string status
|
||||
* @property string created_at
|
||||
* @property string updated_at
|
||||
*/
|
||||
class TeamFolderInvitation extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $casts = [
|
||||
'id' => 'string',
|
||||
];
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public $incrementing = false;
|
||||
|
||||
protected $keyType = 'string';
|
||||
|
||||
public function accept()
|
||||
{
|
||||
$this->update([
|
||||
'status' => 'accepted',
|
||||
]);
|
||||
}
|
||||
|
||||
public function reject()
|
||||
{
|
||||
$this->update([
|
||||
'status' => 'rejected',
|
||||
]);
|
||||
}
|
||||
|
||||
protected static function newFactory(): TeamFolderInvitationFactory
|
||||
{
|
||||
return TeamFolderInvitationFactory::new();
|
||||
}
|
||||
|
||||
public function inviter(): HasOne
|
||||
{
|
||||
return $this->hasOne(User::class, 'id', 'inviter_id');
|
||||
}
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function ($invitation) {
|
||||
$invitation->id = Str::uuid();
|
||||
$invitation->color = config('vuefilemanager.colors')[rand(0, 4)];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Database\Factories\TeamFolderMemberFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @method static create(array $array)
|
||||
* @property string id
|
||||
* @property string parent_id
|
||||
* @property string email
|
||||
* @property string status
|
||||
* @property string created_at
|
||||
* @property string updated_at
|
||||
*/
|
||||
class TeamFolderMember extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public $incrementing = false;
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected static function newFactory(): TeamFolderMemberFactory
|
||||
{
|
||||
return TeamFolderMemberFactory::new();
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Notifications;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Domain\Teams\Models\TeamFolderInvitation;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class InvitationIntoTeamFolder extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function __construct(
|
||||
public Folder $teamFolder,
|
||||
public TeamFolderInvitation $invitation,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*/
|
||||
public function via(): array
|
||||
{
|
||||
return ['mail', 'database', 'broadcast'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*/
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
$appTitle = get_settings('app_title') ?? 'VueFileManager';
|
||||
|
||||
$user = User::find($this->invitation->email);
|
||||
|
||||
if ($user) {
|
||||
return (new MailMessage)
|
||||
->subject(__t('team_invitation_notify_title', ['app' => $appTitle]))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('team_invitation_notify_desc'))
|
||||
->action(__t('join_into_team_folder'), url('/team-folder-invitation', ['id' => $this->invitation->id]))
|
||||
->salutation(__t('salutation') . ', ' . $appTitle);
|
||||
}
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(__t('team_invitation_notify_title', ['app' => $appTitle]))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('team_invitation_notify_desc_without_account'))
|
||||
->action(__t('join_and_create_account'), url('/team-folder-invitation', ['id' => $this->invitation->id]))
|
||||
->salutation(__t('salutation') . ', ' . $appTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*/
|
||||
public function toArray(mixed $notifiable): array
|
||||
{
|
||||
return [
|
||||
'category' => 'team-invitation',
|
||||
'title' => __t('new_team_invitation'),
|
||||
'description' => __t('x_invite_to_join_team', ['name' => $this->invitation->inviter->settings->name, ]),
|
||||
'action' => [
|
||||
'type' => 'invitation',
|
||||
'params' => [
|
||||
'id' => $this->invitation->id,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ConvertIntoTeamFolderRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'invitations' => 'required|array',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CreateTeamFolderRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string',
|
||||
'invitations' => 'required|array',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateTeamFolderMembersRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'members' => 'present|array',
|
||||
'invitations' => 'present|array',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Resources;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TeamInvitationResource extends JsonResource
|
||||
{
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => 'invitation',
|
||||
'attributes' => [
|
||||
'parent_id' => $this->parent_id,
|
||||
'email' => $this->email,
|
||||
'color' => $this->color,
|
||||
'status' => $this->status,
|
||||
'permission' => $this->permission,
|
||||
'isExistedUser' => User::where('email', $this->email)->exists(),
|
||||
],
|
||||
'relationships' => [
|
||||
$this->mergeWhen($this->inviter, fn () => [
|
||||
'inviter' => [
|
||||
'data' => [
|
||||
'type' => 'user',
|
||||
'id' => $this->inviter->id,
|
||||
'attributes' => [
|
||||
'name' => $this->inviter->settings->name,
|
||||
'avatar' => $this->inviter->settings->avatar,
|
||||
'color' => $this->inviter->settings->color,
|
||||
],
|
||||
],
|
||||
],
|
||||
]),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class TeamInvitationsCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = TeamInvitationResource::class;
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TeamMemberResource extends JsonResource
|
||||
{
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => 'member',
|
||||
'attributes' => [
|
||||
'email' => $this->email,
|
||||
'name' => $this->settings->name,
|
||||
'avatar' => $this->settings->avatar,
|
||||
'color' => $this->settings->color,
|
||||
'permission' => $this->pivot->permission,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Teams\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class TeamMembersCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = TeamMemberResource::class;
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Transactions\Controllers;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Transactions\Resources\TransactionCollection;
|
||||
use VueFileManager\Subscription\Domain\Transactions\Models\Transaction;
|
||||
|
||||
class GetAllTransactionsController extends Controller
|
||||
{
|
||||
public function __invoke(User $user)
|
||||
{
|
||||
$transactions = Transaction::with('user')
|
||||
->sortable(['created_at' => 'desc'])
|
||||
->paginate(20);
|
||||
|
||||
return new TransactionCollection($transactions);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Transactions\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Domain\Transactions\Resources\TransactionCollection;
|
||||
|
||||
class GetTransactionsController extends Controller
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
$transactions = Auth::user()
|
||||
->transactions()
|
||||
->sortable(['created_at' => 'desc'])
|
||||
->paginate(15);
|
||||
|
||||
return new TransactionCollection($transactions);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Transactions\Controllers;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Transactions\Resources\TransactionCollection;
|
||||
|
||||
class GetUserTransactionsController extends Controller
|
||||
{
|
||||
public function __invoke(User $user)
|
||||
{
|
||||
$transactions = $user
|
||||
->transactions()
|
||||
->sortable(['created_at' => 'desc'])
|
||||
->paginate(20);
|
||||
|
||||
return new TransactionCollection($transactions);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Transactions\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class TransactionCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = TransactionResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\Transactions\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use App\Users\Actions\FormatUsageEstimatesAction;
|
||||
|
||||
class TransactionResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => 'transactions',
|
||||
'attributes' => [
|
||||
'type' => $this->type,
|
||||
'status' => $this->status,
|
||||
'note' => $this->note,
|
||||
'price' => format_currency($this->amount, $this->currency),
|
||||
'currency' => $this->currency,
|
||||
'amount' => $this->amount,
|
||||
'driver' => $this->driver,
|
||||
'reference' => $this->reference,
|
||||
'metadata' => $this->metadata
|
||||
? resolve(FormatUsageEstimatesAction::class)($this->currency, $this->metadata)
|
||||
: null,
|
||||
'created_at' => format_date($this->created_at, 'd. M. Y'),
|
||||
'updated_at' => format_date($this->updated_at, 'd. M. Y'),
|
||||
],
|
||||
'relationships' => [
|
||||
$this->mergeWhen($this->user && $this->user->settings, fn () => [
|
||||
'user' => [
|
||||
'data' => [
|
||||
'id' => $this->user->id,
|
||||
'type' => 'users',
|
||||
'attributes' => [
|
||||
'avatar' => $this->user->settings->avatar,
|
||||
'first_name' => $this->user->settings->first_name,
|
||||
'last_name' => $this->user->settings->last_name,
|
||||
'name' => $this->user->settings->name,
|
||||
'color' => $this->user->settings->color,
|
||||
'email' => $this->user->email,
|
||||
],
|
||||
],
|
||||
],
|
||||
]),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Domain\Files\Models\File;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Files\Resources\FilesCollection;
|
||||
use Domain\Folders\Resources\FolderResource;
|
||||
use Domain\Folders\Resources\FolderCollection;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
|
||||
class BrowseUploadRequestController extends Controller
|
||||
{
|
||||
public function __invoke(UploadRequest $uploadRequest, $id): array
|
||||
{
|
||||
$rootId = Str::isUuid($id) ? $id : $uploadRequest->id;
|
||||
|
||||
$folders = Folder::with(['parent:id,name'])
|
||||
->where('parent_id', $rootId)
|
||||
->where('user_id', $uploadRequest->user_id)
|
||||
->sortable()
|
||||
->get();
|
||||
|
||||
// TODO: security check
|
||||
$files = File::with(['parent:id,name'])
|
||||
->where('parent_id', $rootId)
|
||||
->where('user_id', $uploadRequest->user_id)
|
||||
->sortable()
|
||||
->get()
|
||||
->each(fn ($file) => $file->setUploadRequestPublicUrl($uploadRequest->id));
|
||||
|
||||
// Collect folders and files to single array
|
||||
return [
|
||||
'folders' => new FolderCollection($folders),
|
||||
'files' => new FilesCollection($files),
|
||||
'root' => new FolderResource(Folder::find($rootId)),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Domain\Folders\Resources\FolderResource;
|
||||
use Domain\Folders\Actions\CreateFolderAction;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Domain\Folders\Requests\CreateFolderRequest;
|
||||
use Support\Demo\Actions\FakeCreateFolderAction;
|
||||
|
||||
class CreateFolderController
|
||||
{
|
||||
public function __construct(
|
||||
public CreateFolderAction $createFolder,
|
||||
public FakeCreateFolderAction $fakeCreateFolder,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(CreateFolderRequest $request, UploadRequest $uploadRequest)
|
||||
{
|
||||
// Check privileges
|
||||
if (! in_array($request->input('parent_id'), getChildrenFolderIds($uploadRequest->id))) {
|
||||
return response('Access Denied', 403);
|
||||
}
|
||||
|
||||
// Create new folder
|
||||
$folder = Folder::create([
|
||||
'parent_id' => $request->input('parent_id'),
|
||||
'name' => $request->input('name'),
|
||||
'color' => $request->input('color') ?? null,
|
||||
'emoji' => $request->input('emoji') ?? null,
|
||||
'author' => 'visitor',
|
||||
'user_id' => $uploadRequest->user_id,
|
||||
'team_folder' => false,
|
||||
]);
|
||||
|
||||
// Return new folder
|
||||
return response(new FolderResource($folder), 201);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Notification;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\UploadRequest\Requests\StoreUploadRequest;
|
||||
use Domain\UploadRequest\Resources\UploadRequestResource;
|
||||
use Domain\UploadRequest\Notifications\UploadRequestNotification;
|
||||
|
||||
class CreateUploadRequestController extends Controller
|
||||
{
|
||||
public function __invoke(StoreUploadRequest $request)
|
||||
{
|
||||
$uploadRequest = Auth::user()->uploadRequest()->create([
|
||||
'folder_id' => $request->input('folder_id'),
|
||||
'email' => $request->input('email'),
|
||||
'notes' => $request->input('notes'),
|
||||
'name' => $request->input('name'),
|
||||
]);
|
||||
|
||||
// If user type email, notify by email
|
||||
if ($uploadRequest->email) {
|
||||
Notification::route('mail', $uploadRequest->email)
|
||||
->notify(new UploadRequestNotification($uploadRequest));
|
||||
}
|
||||
|
||||
return response(new UploadRequestResource($uploadRequest), 201);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Domain\Files\Models\File;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Domain\Items\Requests\DeleteItemRequest;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
|
||||
class DeleteFileOrFolderController
|
||||
{
|
||||
public function __invoke(DeleteItemRequest $request, UploadRequest $uploadRequest)
|
||||
{
|
||||
foreach ($request->input('items') as $file) {
|
||||
// Get file or folder item
|
||||
$item = get_item($file['type'], $file['id']);
|
||||
|
||||
// Delete folder
|
||||
if ($file['type'] === 'folder') {
|
||||
$this->destroyFolder($item);
|
||||
}
|
||||
|
||||
// Delete file
|
||||
if ($file['type'] !== 'folder') {
|
||||
$this->destroyFile($item);
|
||||
}
|
||||
}
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
private function destroyFile(File $file): void
|
||||
{
|
||||
// Delete file
|
||||
Storage::delete("/files/$file->user_id/$file->basename");
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->type === 'image') {
|
||||
getThumbnailFileList($file->basename)
|
||||
->each(fn ($thumbnail) => Storage::delete("files/$file->user_id/$thumbnail"));
|
||||
}
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
private function destroyFolder(Folder $folder): void
|
||||
{
|
||||
// Get children files
|
||||
$files = File::whereIn('parent_id', Arr::flatten([filter_folders_ids($folder->folders), $folder->id]))
|
||||
->get();
|
||||
|
||||
// Remove all children files
|
||||
foreach ($files as $file) {
|
||||
// Delete file
|
||||
Storage::delete("/files/$file->user_id/$file->basename");
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->type === 'image') {
|
||||
getThumbnailFileList($file->basename)
|
||||
->each(fn ($thumbnail) => Storage::delete("files/$file->user_id/$thumbnail"));
|
||||
}
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
$folder->forceDelete();
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers\FileAccess;
|
||||
|
||||
use Domain\Files\Models\File;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Domain\Files\Actions\DownloadFileAction;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Domain\Traffic\Actions\RecordDownloadAction;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Get shared file record
|
||||
*/
|
||||
class GetFileFromUploadRequestController
|
||||
{
|
||||
public function __construct(
|
||||
private DownloadFileAction $downloadFile,
|
||||
private RecordDownloadAction $recordDownload,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
string $filename,
|
||||
UploadRequest $uploadRequest
|
||||
): StreamedResponse|RedirectResponse|Response {
|
||||
// Get file
|
||||
$file = File::where('user_id', $uploadRequest->user_id)
|
||||
->where('basename', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Store user download size
|
||||
($this->recordDownload)(
|
||||
file_size: $file->filesize,
|
||||
user_id: $uploadRequest->user_id,
|
||||
);
|
||||
|
||||
// Finally, download file
|
||||
return ($this->downloadFile)($file);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers\FileAccess;
|
||||
|
||||
use Domain\Files\Models\File;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Domain\Traffic\Actions\RecordDownloadAction;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Domain\Files\Actions\DownloadThumbnailAction;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Get shared file record
|
||||
*/
|
||||
class GetThumbnailFromUploadRequestController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private DownloadThumbnailAction $downloadThumbnail,
|
||||
private RecordDownloadAction $recordDownload,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
string $filename,
|
||||
UploadRequest $uploadRequest
|
||||
): Application|ResponseFactory|Response|StreamedResponse {
|
||||
// Get file
|
||||
$file = File::where('user_id', $uploadRequest->user_id)
|
||||
->where('basename', substr($filename, 3))
|
||||
->firstOrFail();
|
||||
|
||||
// Store user download size
|
||||
($this->recordDownload)(
|
||||
file_size: $file->filesize,
|
||||
user_id: $uploadRequest->user_id,
|
||||
);
|
||||
|
||||
// Finally, download thumbnail
|
||||
return ($this->downloadThumbnail)($filename, $file);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
|
||||
class GetFolderTreeForUploadRequestController extends Controller
|
||||
{
|
||||
public function __invoke(UploadRequest $uploadRequest): Application|ResponseFactory|Response|array
|
||||
{
|
||||
// Get folders
|
||||
$folders = Folder::with('folders:id,parent_id,name')
|
||||
->whereParentId($uploadRequest->id)
|
||||
->whereUserId($uploadRequest->user_id)
|
||||
->sortable()
|
||||
->get(['id', 'parent_id', 'id', 'name']);
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => __t('upload_request'),
|
||||
'location' => 'upload-request',
|
||||
'folders' => $folders,
|
||||
'isMovable' => true,
|
||||
'isOpen' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Domain\UploadRequest\Resources\UploadRequestResource;
|
||||
|
||||
class GetUploadRequestController
|
||||
{
|
||||
public function __invoke(UploadRequest $uploadRequest)
|
||||
{
|
||||
return new UploadRequestResource($uploadRequest);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Items\Requests\MoveItemRequest;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
|
||||
class MoveItemInUploadRequestController extends Controller
|
||||
{
|
||||
public function __invoke(
|
||||
MoveItemRequest $request,
|
||||
UploadRequest $uploadRequest,
|
||||
) {
|
||||
foreach ($request->input('items') as $item) {
|
||||
$item = get_item($item['type'], $item['id']);
|
||||
|
||||
// Check privileges
|
||||
if (! in_array($item['parent_id'], getChildrenFolderIds($uploadRequest->id))) {
|
||||
return response('Access Denied', 403);
|
||||
}
|
||||
|
||||
$item->update(['parent_id' => $request->input('to_id') ?? $uploadRequest->id]);
|
||||
}
|
||||
|
||||
return response('Done.', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Files\Resources\FileResource;
|
||||
use Domain\Folders\Resources\FolderResource;
|
||||
use Domain\Items\Requests\RenameItemRequest;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Domain\Folders\Actions\UpdateFolderPropertyAction;
|
||||
use Support\Demo\Actions\FakeRenameFileOrFolderAction;
|
||||
|
||||
class RenameFileOrFolderController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public UpdateFolderPropertyAction $updateFolderProperty,
|
||||
public FakeRenameFileOrFolderAction $fakeRenameFileOrFolder,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(UploadRequest $uploadRequest, string $id, RenameItemRequest $request)
|
||||
{
|
||||
// Get item
|
||||
$item = get_item($request->input('type'), $id);
|
||||
|
||||
// Check privileges
|
||||
if (! in_array($item->parent_id, getChildrenFolderIds($uploadRequest->id))) {
|
||||
return response('Access Denied', 403);
|
||||
}
|
||||
|
||||
// If request contain icon or color, then change it
|
||||
if ($request->input('type') === 'folder' && $request->hasAny(['emoji', 'color'])) {
|
||||
($this->updateFolderProperty)($request, $id);
|
||||
}
|
||||
|
||||
// Update item
|
||||
$item->update(['name' => $request->input('name')]);
|
||||
|
||||
if ($request->input('type') === 'folder') {
|
||||
return new FolderResource($item);
|
||||
}
|
||||
|
||||
return new FileResource($item);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Domain\UploadRequest\Resources\UploadRequestResource;
|
||||
use Domain\UploadRequest\Notifications\UploadRequestFulfilledNotification;
|
||||
|
||||
class SetUploadRequestAsFilledController
|
||||
{
|
||||
public function __invoke(UploadRequest $uploadRequest): Response|Application|ResponseFactory
|
||||
{
|
||||
$uploadRequest->update([
|
||||
'status' => 'filled',
|
||||
]);
|
||||
|
||||
// Send user notification
|
||||
if ($uploadRequest->user->email !== 'howdy@hi5ve.digital') {
|
||||
$uploadRequest->user->notify(new UploadRequestFulfilledNotification($uploadRequest));
|
||||
}
|
||||
|
||||
return response(new UploadRequestResource($uploadRequest), 201);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Controllers;
|
||||
|
||||
use DB;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Domain\Files\Resources\FileResource;
|
||||
use Domain\Files\Actions\ProcessFileAction;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Domain\Files\Actions\StoreFileChunksAction;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
|
||||
class UploadFilesForUploadRequestController
|
||||
{
|
||||
public function __construct(
|
||||
private ProcessFileAction $processFie,
|
||||
private StoreFileChunksAction $storeFileChunks,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function __invoke(\Domain\Files\Requests\UploadRequest $request, UploadRequest $uploadRequest)
|
||||
{
|
||||
// Get upload request root folder query
|
||||
$folder = Folder::where('id', $uploadRequest->id);
|
||||
|
||||
// Create folder if not exist
|
||||
if ($folder->doesntExist()) {
|
||||
$this->createFolder($uploadRequest);
|
||||
}
|
||||
|
||||
// Set default parent_id for uploaded file
|
||||
if (is_null($request->input('parent_id'))) {
|
||||
$request->merge(['parent_id' => $uploadRequest->id]);
|
||||
}
|
||||
|
||||
// Store file chunks
|
||||
$chunkPath = ($this->storeFileChunks)($request);
|
||||
|
||||
// Proceed after last chunk
|
||||
if ($request->boolean('is_last')) {
|
||||
// Process file
|
||||
$file = ($this->processFie)($request, $uploadRequest->user, $chunkPath);
|
||||
|
||||
// Set public access url
|
||||
$file->setUploadRequestPublicUrl($uploadRequest->id);
|
||||
|
||||
// Set timestamp for auto filling
|
||||
cache()->set("auto-filling.$uploadRequest->id", now()->toString());
|
||||
|
||||
return response(new FileResource($file), 201);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create root Upload Request folder
|
||||
*/
|
||||
private function createFolder(UploadRequest $uploadRequest): void
|
||||
{
|
||||
// Format timestamp
|
||||
$timestamp = format_date($uploadRequest->created_at, 'd. M. Y');
|
||||
|
||||
// Create folder
|
||||
DB::table('folders')->insert([
|
||||
'id' => $uploadRequest->id,
|
||||
'parent_id' => $uploadRequest->folder_id ?? null,
|
||||
'user_id' => $uploadRequest->user_id,
|
||||
'name' => $uploadRequest->name ?? __t('upload_request_default_folder', ['timestamp' => $timestamp]),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
// Update upload request status
|
||||
$uploadRequest->update([
|
||||
'status' => 'filling',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProtectUploadRequestRoutes
|
||||
{
|
||||
/**
|
||||
* Prevent access for setup wizard controllers after initial app installation.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): mixed
|
||||
{
|
||||
// Get upload request
|
||||
$uploadRequest = $request->route()->parameter('uploadRequest');
|
||||
|
||||
// Check if upload request is active
|
||||
if (! in_array($uploadRequest->status, ['active', 'filling'])) {
|
||||
return response('Gone', 410);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Models;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Database\Factories\UploadRequestFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @method static create(array $array)
|
||||
* @property string id
|
||||
* @property string user_id
|
||||
* @property string folder_id
|
||||
* @property string status
|
||||
* @property string email
|
||||
* @property string notes
|
||||
* @property string created_at
|
||||
* @property string updated_at
|
||||
*/
|
||||
class UploadRequest extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $casts = [
|
||||
'id' => 'string',
|
||||
];
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public $incrementing = false;
|
||||
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected static function newFactory(): UploadRequestFactory
|
||||
{
|
||||
return UploadRequestFactory::new();
|
||||
}
|
||||
|
||||
public function user(): HasOne
|
||||
{
|
||||
return $this->hasOne(User::class, 'id', 'user_id');
|
||||
}
|
||||
|
||||
public function folder(): HasOne
|
||||
{
|
||||
return $this->hasOne(Folder::class, 'id', 'id');
|
||||
}
|
||||
|
||||
public function parent(): HasOne
|
||||
{
|
||||
return $this->hasOne(Folder::class, 'id', 'folder_id');
|
||||
}
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(fn ($invitation) => $invitation->id = Str::uuid());
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class UploadRequestFulfilledNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public UploadRequest $uploadRequest
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*/
|
||||
public function via(mixed $notifiable): array
|
||||
{
|
||||
return ['mail', 'database', 'broadcast'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*/
|
||||
public function toMail(mixed $notifiable): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(__t('file_request_filled_mail', ['name' => $this->uploadRequest->parent->name]))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('file_request_filled_mail_note'))
|
||||
->action(__t('show_files'), url("/platform/files/{$this->uploadRequest->id}"))
|
||||
->salutation(__t('thanks_salutation'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*/
|
||||
public function toArray(mixed $notifiable): array
|
||||
{
|
||||
return [
|
||||
'category' => 'file-request',
|
||||
'title' => __t('file_request_filled'),
|
||||
'description' => __t('file_request_filled_desc', ['name' => $this->uploadRequest->parent->name, ]),
|
||||
'action' => [
|
||||
'type' => 'route',
|
||||
'params' => [
|
||||
'route' => 'Files',
|
||||
'button' => __t('show_files'),
|
||||
'id' => $this->uploadRequest->id,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
namespace Domain\UploadRequest\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Domain\UploadRequest\Models\UploadRequest;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class UploadRequestNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public UploadRequest $uploadRequest
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
// Format optional message
|
||||
$message = $this->uploadRequest->notes
|
||||
? __t('file_request_optional_message', ['name' => $this->uploadRequest->user->settings->first_name, 'notes' => $this->uploadRequest->notes])
|
||||
: null;
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(__t('file_request_notify_title', ['name' => $this->uploadRequest->user->settings->first_name]))
|
||||
->greeting(__t('hello'))
|
||||
->line(__t('file_request_notify_description', ['name' => $this->uploadRequest->user->settings->first_name]))
|
||||
->line($message)
|
||||
->action(__t('upload_your_files'), url("/request/{$this->uploadRequest->id}/upload"))
|
||||
->salutation(__t('thanks_salutation'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
];
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user