diff --git a/app/Http/Controllers/ComposeController.php b/app/Http/Controllers/ComposeController.php index 4c27aa18e..cfd44969b 100644 --- a/app/Http/Controllers/ComposeController.php +++ b/app/Http/Controllers/ComposeController.php @@ -21,6 +21,7 @@ use App\Services\MediaStorageService; use App\Services\MediaTagService; use App\Services\SnowflakeService; use App\Services\UserRoleService; +use App\Services\UserStorageService; use App\Status; use App\Transformer\Api\MediaTransformer; use App\UserFilter; @@ -70,7 +71,7 @@ class ComposeController extends Controller 'filter_class' => 'nullable|alpha_dash|max:24', ]); - $user = Auth::user(); + $user = $request->user(); $profile = $user->profile; abort_if($user->has_roles && ! UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); @@ -84,21 +85,22 @@ class ComposeController extends Controller abort_if($limitReached == true, 429); - if (config_cache('pixelfed.enforce_account_limit') == true) { - $size = Cache::remember($user->storageUsedKey(), now()->addDays(3), function () use ($user) { - return Media::whereUserId($user->id)->sum('size') / 1000; - }); + $filterClass = in_array($request->input('filter_class'), Filter::classes()) ? $request->input('filter_class') : null; + $filterName = in_array($request->input('filter_name'), Filter::names()) ? $request->input('filter_name') : null; + $accountSize = UserStorageService::get($user->id); + abort_if($accountSize === -1, 403, 'Invalid request.'); + $photo = $request->file('file'); + $fileSize = $photo->getSize(); + $sizeInKbs = (int) ceil($fileSize / 1000); + $updatedAccountSize = (int) $accountSize + (int) $sizeInKbs; + + if ((bool) config_cache('pixelfed.enforce_account_limit') == true) { $limit = (int) config_cache('pixelfed.max_account_size'); - if ($size >= $limit) { + if ($updatedAccountSize >= $limit) { abort(403, 'Account size limit reached.'); } } - $filterClass = in_array($request->input('filter_class'), Filter::classes()) ? $request->input('filter_class') : null; - $filterName = in_array($request->input('filter_name'), Filter::names()) ? $request->input('filter_name') : null; - - $photo = $request->file('file'); - $mimes = explode(',', config_cache('pixelfed.media_types')); abort_if(in_array($photo->getMimeType(), $mimes) == false, 400, 'Invalid media format'); @@ -143,6 +145,10 @@ class ComposeController extends Controller break; } + $user->storage_used = (int) $updatedAccountSize; + $user->storage_used_updated_at = now(); + $user->save(); + Cache::forget($limitKey); $resource = new Fractal\Resource\Item($media, new MediaTransformer()); $res = $this->fractal->createData($resource)->toArray(); @@ -198,6 +204,7 @@ class ComposeController extends Controller ]; ImageOptimize::dispatch($media)->onQueue('mmo'); Cache::forget($limitKey); + UserStorageService::recalculateUpdateStorageUsed($request->user()->id); return $res; } @@ -218,6 +225,8 @@ class ComposeController extends Controller MediaStorageService::delete($media, true); + UserStorageService::recalculateUpdateStorageUsed($request->user()->id); + return response()->json([ 'msg' => 'Successfully deleted', 'code' => 200, @@ -494,17 +503,17 @@ class ComposeController extends Controller $limitKey = 'compose:rate-limit:store:'.$user->id; $limitTtl = now()->addMinutes(15); - $limitReached = Cache::remember($limitKey, $limitTtl, function () use ($user) { - $dailyLimit = Status::whereProfileId($user->profile_id) - ->whereNull('in_reply_to_id') - ->whereNull('reblog_of_id') - ->where('created_at', '>', now()->subDays(1)) - ->count(); + // $limitReached = Cache::remember($limitKey, $limitTtl, function () use ($user) { + // $dailyLimit = Status::whereProfileId($user->profile_id) + // ->whereNull('in_reply_to_id') + // ->whereNull('reblog_of_id') + // ->where('created_at', '>', now()->subDays(1)) + // ->count(); - return $dailyLimit >= 1000; - }); + // return $dailyLimit >= 1000; + // }); - abort_if($limitReached == true, 429); + // abort_if($limitReached == true, 429); $license = in_array($request->input('license'), License::keys()) ? $request->input('license') : null; @@ -626,7 +635,6 @@ class ComposeController extends Controller Cache::forget('_api:statuses:recent_9:'.$profile->id); Cache::forget('profile:status_count:'.$profile->id); Cache::forget('status:transformer:media:attachments:'.$status->id); - Cache::forget($user->storageUsedKey()); Cache::forget('profile:embed:'.$status->profile_id); Cache::forget($limitKey); diff --git a/app/Http/Controllers/DirectMessageController.php b/app/Http/Controllers/DirectMessageController.php index 7e66d30fc..1a30032cd 100644 --- a/app/Http/Controllers/DirectMessageController.php +++ b/app/Http/Controllers/DirectMessageController.php @@ -17,11 +17,11 @@ use App\Services\MediaService; use App\Services\StatusService; use App\Services\UserFilterService; use App\Services\UserRoleService; +use App\Services\UserStorageService; use App\Services\WebfingerService; use App\Status; use App\UserFilter; use App\Util\ActivityPub\Helpers; -use Cache; use Illuminate\Http\Request; use Illuminate\Support\Str; @@ -602,16 +602,19 @@ class DirectMessageController extends Controller $hidden = false; } - if (config_cache('pixelfed.enforce_account_limit') == true) { - $size = Cache::remember($user->storageUsedKey(), now()->addDays(3), function () use ($user) { - return Media::whereUserId($user->id)->sum('size') / 1000; - }); + $accountSize = UserStorageService::get($user->id); + abort_if($accountSize === -1, 403, 'Invalid request.'); + $photo = $request->file('file'); + $fileSize = $photo->getSize(); + $sizeInKbs = (int) ceil($fileSize / 1000); + $updatedAccountSize = (int) $accountSize + (int) $sizeInKbs; + + if ((bool) config_cache('pixelfed.enforce_account_limit') == true) { $limit = (int) config_cache('pixelfed.max_account_size'); - if ($size >= $limit) { + if ($updatedAccountSize >= $limit) { abort(403, 'Account size limit reached.'); } } - $photo = $request->file('file'); $mimes = explode(',', config_cache('pixelfed.media_types')); if (in_array($photo->getMimeType(), $mimes) == false) { @@ -667,6 +670,10 @@ class DirectMessageController extends Controller ] ); + $user->storage_used = (int) $updatedAccountSize; + $user->storage_used_updated_at = now(); + $user->save(); + if ($recipient->domain) { $this->remoteDeliver($dm); } diff --git a/database/migrations/2024_07_29_081002_add_storage_used_to_users_table.php b/database/migrations/2024_07_29_081002_add_storage_used_to_users_table.php new file mode 100644 index 000000000..d794b945e --- /dev/null +++ b/database/migrations/2024_07_29_081002_add_storage_used_to_users_table.php @@ -0,0 +1,30 @@ +unsignedBigInteger('storage_used')->default(0); + $table->timestamp('storage_used_updated_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('storage_used'); + $table->dropColumn('storage_used_updated_at'); + }); + } +};