From 5e4d4eff9dbaa24cdcf0b853ab72d145cd1a3998 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 10 Mar 2024 04:19:44 -0600 Subject: [PATCH] Update config cache --- app/Http/Controllers/Api/ApiV1Controller.php | 4 +- app/Http/Controllers/Api/ApiV2Controller.php | 2 +- app/Http/Controllers/CommentController.php | 35 +- app/Http/Controllers/ComposeController.php | 398 +++++++++--------- app/Services/ConfigCacheService.php | 12 + app/Services/LandingService.php | 173 ++++---- app/Util/Site/Config.php | 41 +- .../views/site/help/sharing-media.blade.php | 2 +- 8 files changed, 329 insertions(+), 338 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 5ab69dfc9..0463e681e 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -1664,7 +1664,7 @@ class ApiV1Controller extends Controller ], 'statuses' => [ 'characters_reserved_per_url' => 23, - 'max_characters' => (int) config('pixelfed.max_caption_length'), + 'max_characters' => (int) config_cache('pixelfed.max_caption_length'), 'max_media_attachments' => (int) config('pixelfed.max_album_length'), ], ], @@ -3308,7 +3308,7 @@ class ApiV1Controller extends Controller abort_unless($request->user()->tokenCan('write'), 403); $this->validate($request, [ - 'status' => 'nullable|string', + 'status' => 'nullable|string|max:' . config_cache('pixelfed.max_caption_length'), 'in_reply_to_id' => 'nullable', 'media_ids' => 'sometimes|array|max:'.config_cache('pixelfed.max_album_length'), 'sensitive' => 'nullable', diff --git a/app/Http/Controllers/Api/ApiV2Controller.php b/app/Http/Controllers/Api/ApiV2Controller.php index c585b3b04..ebdc851b8 100644 --- a/app/Http/Controllers/Api/ApiV2Controller.php +++ b/app/Http/Controllers/Api/ApiV2Controller.php @@ -104,7 +104,7 @@ class ApiV2Controller extends Controller 'max_featured_tags' => 0, ], 'statuses' => [ - 'max_characters' => (int) config('pixelfed.max_caption_length'), + 'max_characters' => (int) config_cache('pixelfed.max_caption_length'), 'max_media_attachments' => (int) config_cache('pixelfed.max_album_length'), 'characters_reserved_per_url' => 23 ], diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 42a5490d0..1dd985723 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -2,23 +2,18 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; -use Auth; -use DB; -use Cache; - -use App\Comment; use App\Jobs\CommentPipeline\CommentPipeline; use App\Jobs\StatusPipeline\NewStatusPipeline; -use App\Util\Lexer\Autolink; -use App\Profile; -use App\Status; -use App\UserFilter; -use League\Fractal; -use App\Transformer\Api\StatusTransformer; -use League\Fractal\Serializer\ArraySerializer; -use League\Fractal\Pagination\IlluminatePaginatorAdapter; use App\Services\StatusService; +use App\Status; +use App\Transformer\Api\StatusTransformer; +use App\UserFilter; +use App\Util\Lexer\Autolink; +use Auth; +use DB; +use Illuminate\Http\Request; +use League\Fractal; +use League\Fractal\Serializer\ArraySerializer; class CommentController extends Controller { @@ -33,9 +28,9 @@ class CommentController extends Controller abort(403); } $this->validate($request, [ - 'item' => 'required|integer|min:1', - 'comment' => 'required|string|max:'.(int) config('pixelfed.max_caption_length'), - 'sensitive' => 'nullable|boolean' + 'item' => 'required|integer|min:1', + 'comment' => 'required|string|max:'.config_cache('pixelfed.max_caption_length'), + 'sensitive' => 'nullable|boolean', ]); $comment = $request->input('comment'); $statusId = $request->input('item'); @@ -45,7 +40,7 @@ class CommentController extends Controller $profile = $user->profile; $status = Status::findOrFail($statusId); - if($status->comments_disabled == true) { + if ($status->comments_disabled == true) { return; } @@ -55,11 +50,11 @@ class CommentController extends Controller ->whereFilterableId($profile->id) ->exists(); - if($filtered == true) { + if ($filtered == true) { return; } - $reply = DB::transaction(function() use($comment, $status, $profile, $nsfw) { + $reply = DB::transaction(function () use ($comment, $status, $profile, $nsfw) { $scope = $profile->is_private == true ? 'private' : 'public'; $autolink = Autolink::create()->autolink($comment); $reply = new Status(); diff --git a/app/Http/Controllers/ComposeController.php b/app/Http/Controllers/ComposeController.php index 36bd5a66c..341d56ea8 100644 --- a/app/Http/Controllers/ComposeController.php +++ b/app/Http/Controllers/ComposeController.php @@ -2,59 +2,38 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; -use Auth, Cache, DB, Storage, URL; -use Carbon\Carbon; -use App\{ - Avatar, - Collection, - CollectionItem, - Hashtag, - Like, - Media, - MediaTag, - Notification, - Profile, - Place, - Status, - UserFilter, - UserSetting -}; -use App\Models\Poll; -use App\Transformer\Api\{ - MediaTransformer, - MediaDraftTransformer, - StatusTransformer, - StatusStatelessTransformer -}; -use League\Fractal; -use App\Util\Media\Filter; -use League\Fractal\Serializer\ArraySerializer; -use League\Fractal\Pagination\IlluminatePaginatorAdapter; -use App\Jobs\AvatarPipeline\AvatarOptimize; +use App\Collection; +use App\CollectionItem; +use App\Hashtag; use App\Jobs\ImageOptimizePipeline\ImageOptimize; -use App\Jobs\ImageOptimizePipeline\ImageThumbnail; use App\Jobs\StatusPipeline\NewStatusPipeline; -use App\Jobs\VideoPipeline\{ - VideoOptimize, - VideoPostProcess, - VideoThumbnail -}; +use App\Jobs\VideoPipeline\VideoThumbnail; +use App\Media; +use App\MediaTag; +use App\Models\Poll; +use App\Notification; +use App\Profile; use App\Services\AccountService; use App\Services\CollectionService; -use App\Services\NotificationService; -use App\Services\MediaPathService; use App\Services\MediaBlocklistService; +use App\Services\MediaPathService; use App\Services\MediaStorageService; use App\Services\MediaTagService; -use App\Services\StatusService; use App\Services\SnowflakeService; -use Illuminate\Support\Str; -use App\Util\Lexer\Autolink; -use App\Util\Lexer\Extractor; -use App\Util\Media\License; -use Image; use App\Services\UserRoleService; +use App\Status; +use App\Transformer\Api\MediaTransformer; +use App\UserFilter; +use App\Util\Lexer\Autolink; +use App\Util\Media\Filter; +use App\Util\Media\License; +use Auth; +use Cache; +use DB; +use Illuminate\Http\Request; +use Illuminate\Support\Str; +use League\Fractal; +use League\Fractal\Serializer\ArraySerializer; class ComposeController extends Controller { @@ -74,30 +53,30 @@ class ComposeController extends Controller public function mediaUpload(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ 'file.*' => [ 'required_without:file', - 'mimetypes:' . config_cache('pixelfed.media_types'), - 'max:' . config_cache('pixelfed.max_photo_size'), + 'mimetypes:'.config_cache('pixelfed.media_types'), + 'max:'.config_cache('pixelfed.max_photo_size'), ], 'file' => [ 'required_without:file.*', - 'mimetypes:' . config_cache('pixelfed.media_types'), - 'max:' . config_cache('pixelfed.max_photo_size'), + 'mimetypes:'.config_cache('pixelfed.media_types'), + 'max:'.config_cache('pixelfed.max_photo_size'), ], 'filter_name' => 'nullable|string|max:24', - 'filter_class' => 'nullable|alpha_dash|max:24' + 'filter_class' => 'nullable|alpha_dash|max:24', ]); $user = Auth::user(); $profile = $user->profile; - abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); + abort_if($user->has_roles && ! UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); - $limitKey = 'compose:rate-limit:media-upload:' . $user->id; + $limitKey = 'compose:rate-limit:media-upload:'.$user->id; $limitTtl = now()->addMinutes(15); - $limitReached = Cache::remember($limitKey, $limitTtl, function() use($user) { + $limitReached = Cache::remember($limitKey, $limitTtl, function () use ($user) { $dailyLimit = Media::whereUserId($user->id)->where('created_at', '>', now()->subDays(1))->count(); return $dailyLimit >= 1250; @@ -105,8 +84,8 @@ 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) { + 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; }); $limit = (int) config_cache('pixelfed.max_account_size'); @@ -144,24 +123,24 @@ class ComposeController extends Controller $media->version = 3; $media->save(); - $preview_url = $media->url() . '?v=' . time(); - $url = $media->url() . '?v=' . time(); + $preview_url = $media->url().'?v='.time(); + $url = $media->url().'?v='.time(); switch ($media->mime) { case 'image/jpeg': case 'image/png': case 'image/webp': - ImageOptimize::dispatch($media)->onQueue('mmo'); - break; + ImageOptimize::dispatch($media)->onQueue('mmo'); + break; case 'video/mp4': - VideoThumbnail::dispatch($media)->onQueue('mmo'); - $preview_url = '/storage/no-preview.png'; - $url = '/storage/no-preview.png'; - break; + VideoThumbnail::dispatch($media)->onQueue('mmo'); + $preview_url = '/storage/no-preview.png'; + $url = '/storage/no-preview.png'; + break; default: - break; + break; } Cache::forget($limitKey); @@ -169,6 +148,7 @@ class ComposeController extends Controller $res = $this->fractal->createData($resource)->toArray(); $res['preview_url'] = $preview_url; $res['url'] = $url; + return response()->json($res); } @@ -176,21 +156,21 @@ class ComposeController extends Controller { $this->validate($request, [ 'id' => 'required', - 'file' => function() { + 'file' => function () { return [ 'required', - 'mimetypes:' . config_cache('pixelfed.media_types'), - 'max:' . config_cache('pixelfed.max_photo_size'), + 'mimetypes:'.config_cache('pixelfed.media_types'), + 'max:'.config_cache('pixelfed.max_photo_size'), ]; }, ]); $user = Auth::user(); - abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); + abort_if($user->has_roles && ! UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); - $limitKey = 'compose:rate-limit:media-updates:' . $user->id; + $limitKey = 'compose:rate-limit:media-updates:'.$user->id; $limitTtl = now()->addMinutes(15); - $limitReached = Cache::remember($limitKey, $limitTtl, function() use($user) { + $limitReached = Cache::remember($limitKey, $limitTtl, function () use ($user) { $dailyLimit = Media::whereUserId($user->id)->where('created_at', '>', now()->subDays(1))->count(); return $dailyLimit >= 1500; @@ -202,9 +182,9 @@ class ComposeController extends Controller $id = $request->input('id'); $media = Media::whereUserId($user->id) - ->whereProfileId($user->profile_id) - ->whereNull('status_id') - ->findOrFail($id); + ->whereProfileId($user->profile_id) + ->whereNull('status_id') + ->findOrFail($id); $media->save(); @@ -214,47 +194,48 @@ class ComposeController extends Controller $dir = implode('/', $fragments); $path = $photo->storePubliclyAs($dir, $name); $res = [ - 'url' => $media->url() . '?v=' . time() + 'url' => $media->url().'?v='.time(), ]; ImageOptimize::dispatch($media)->onQueue('mmo'); Cache::forget($limitKey); + return $res; } public function mediaDelete(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ - 'id' => 'required|integer|min:1|exists:media,id' + 'id' => 'required|integer|min:1|exists:media,id', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $media = Media::whereNull('status_id') - ->whereUserId(Auth::id()) - ->findOrFail($request->input('id')); + ->whereUserId(Auth::id()) + ->findOrFail($request->input('id')); MediaStorageService::delete($media, true); return response()->json([ 'msg' => 'Successfully deleted', - 'code' => 200 + 'code' => 200, ]); } public function searchTag(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ - 'q' => 'required|string|min:1|max:50' + 'q' => 'required|string|min:1|max:50', ]); $q = $request->input('q'); - if(Str::of($q)->startsWith('@')) { - if(strlen($q) < 3) { + if (Str::of($q)->startsWith('@')) { + if (strlen($q) < 3) { return []; } $q = mb_substr($q, 1); @@ -262,7 +243,7 @@ class ComposeController extends Controller $user = $request->user(); - abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); + abort_if($user->has_roles && ! UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); $blocked = UserFilter::whereFilterableType('App\Profile') ->whereFilterType('block') @@ -271,34 +252,34 @@ class ComposeController extends Controller $blocked->push($request->user()->profile_id); - $results = Profile::select('id','domain','username') + $results = Profile::select('id', 'domain', 'username') ->whereNotIn('id', $blocked) ->whereNull('domain') - ->where('username','like','%'.$q.'%') + ->where('username', 'like', '%'.$q.'%') ->limit(15) ->get() - ->map(function($r) { + ->map(function ($r) { return [ 'id' => (string) $r->id, 'name' => $r->username, 'privacy' => true, - 'avatar' => $r->avatarUrl() + 'avatar' => $r->avatarUrl(), ]; - }); + }); return $results; } public function searchUntag(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ 'status_id' => 'required', - 'profile_id' => 'required' + 'profile_id' => 'required', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $user = $request->user(); $status_id = $request->input('status_id'); @@ -310,7 +291,7 @@ class ComposeController extends Controller ->whereProfileId($profile_id) ->first(); - if(!$tag) { + if (! $tag) { return []; } Notification::whereItemType('App\MediaTag') @@ -326,37 +307,38 @@ class ComposeController extends Controller public function searchLocation(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ - 'q' => 'required|string|max:100' + 'q' => 'required|string|max:100', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $pid = $request->user()->profile_id; - abort_if(!$pid, 400); + abort_if(! $pid, 400); $q = e($request->input('q')); - $popular = Cache::remember('pf:search:location:v1:popular', 1209600, function() { + $popular = Cache::remember('pf:search:location:v1:popular', 1209600, function () { $minId = SnowflakeService::byDate(now()->subDays(290)); - if(config('database.default') == 'pgsql') { + if (config('database.default') == 'pgsql') { return Status::selectRaw('id, place_id, count(place_id) as pc') - ->whereNotNull('place_id') - ->where('id', '>', $minId) - ->orderByDesc('pc') - ->groupBy(['place_id', 'id']) - ->limit(400) - ->get() - ->filter(function($post) { - return $post; - }) - ->map(function($place) { - return [ - 'id' => $place->place_id, - 'count' => $place->pc - ]; - }) - ->unique('id') - ->values(); + ->whereNotNull('place_id') + ->where('id', '>', $minId) + ->orderByDesc('pc') + ->groupBy(['place_id', 'id']) + ->limit(400) + ->get() + ->filter(function ($post) { + return $post; + }) + ->map(function ($place) { + return [ + 'id' => $place->place_id, + 'count' => $place->pc, + ]; + }) + ->unique('id') + ->values(); } + return Status::selectRaw('id, place_id, count(place_id) as pc') ->whereNotNull('place_id') ->where('id', '>', $minId) @@ -364,57 +346,58 @@ class ComposeController extends Controller ->orderByDesc('pc') ->limit(400) ->get() - ->filter(function($post) { + ->filter(function ($post) { return $post; }) - ->map(function($place) { + ->map(function ($place) { return [ 'id' => $place->place_id, - 'count' => $place->pc + 'count' => $place->pc, ]; }); }); - $q = '%' . $q . '%'; + $q = '%'.$q.'%'; $wildcard = config('database.default') === 'pgsql' ? 'ilike' : 'like'; $places = DB::table('places') - ->where('name', $wildcard, $q) - ->limit((strlen($q) > 5 ? 360 : 30)) - ->get() - ->sortByDesc(function($place, $key) use($popular) { - return $popular->filter(function($p) use($place) { - return $p['id'] == $place->id; - })->map(function($p) use($place) { - return in_array($place->country, ['Canada', 'USA', 'France', 'Germany', 'United Kingdom']) ? $p['count'] : 1; - })->values(); - }) - ->map(function($r) { - return [ - 'id' => $r->id, - 'name' => $r->name, - 'country' => $r->country, - 'url' => url('/discover/places/' . $r->id . '/' . $r->slug) - ]; - }) - ->values() - ->all(); + ->where('name', $wildcard, $q) + ->limit((strlen($q) > 5 ? 360 : 30)) + ->get() + ->sortByDesc(function ($place, $key) use ($popular) { + return $popular->filter(function ($p) use ($place) { + return $p['id'] == $place->id; + })->map(function ($p) use ($place) { + return in_array($place->country, ['Canada', 'USA', 'France', 'Germany', 'United Kingdom']) ? $p['count'] : 1; + })->values(); + }) + ->map(function ($r) { + return [ + 'id' => $r->id, + 'name' => $r->name, + 'country' => $r->country, + 'url' => url('/discover/places/'.$r->id.'/'.$r->slug), + ]; + }) + ->values() + ->all(); + return $places; } public function searchMentionAutocomplete(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ - 'q' => 'required|string|min:2|max:50' + 'q' => 'required|string|min:2|max:50', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $q = $request->input('q'); - if(Str::of($q)->startsWith('@')) { - if(strlen($q) < 3) { + if (Str::of($q)->startsWith('@')) { + if (strlen($q) < 3) { return []; } } @@ -426,32 +409,33 @@ class ComposeController extends Controller $blocked->push($request->user()->profile_id); - $results = Profile::select('id','domain','username') + $results = Profile::select('id', 'domain', 'username') ->whereNotIn('id', $blocked) - ->where('username','like','%'.$q.'%') + ->where('username', 'like', '%'.$q.'%') ->groupBy('id', 'domain') ->limit(15) ->get() - ->map(function($profile) { + ->map(function ($profile) { $username = $profile->domain ? substr($profile->username, 1) : $profile->username; + return [ - 'key' => '@' . str_limit($username, 30), + 'key' => '@'.str_limit($username, 30), 'value' => $username, ]; - }); + }); return $results; } public function searchHashtagAutocomplete(Request $request) { - abort_if(!$request->user(), 403); + abort_if(! $request->user(), 403); $this->validate($request, [ - 'q' => 'required|string|min:2|max:50' + 'q' => 'required|string|min:2|max:50', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $q = $request->input('q'); @@ -461,12 +445,12 @@ class ComposeController extends Controller ->whereIsBanned(false) ->limit(5) ->get() - ->map(function($tag) { + ->map(function ($tag) { return [ - 'key' => '#' . $tag->slug, - 'value' => $tag->slug + 'key' => '#'.$tag->slug, + 'value' => $tag->slug, ]; - }); + }); return $results; } @@ -474,8 +458,8 @@ class ComposeController extends Controller public function store(Request $request) { $this->validate($request, [ - 'caption' => 'nullable|string|max:'.config('pixelfed.max_caption_length', 500), - 'media.*' => 'required', + 'caption' => 'nullable|string|max:'.config_cache('pixelfed.max_caption_length', 500), + 'media.*' => 'required', 'media.*.id' => 'required|integer|min:1', 'media.*.filter_class' => 'nullable|alpha_dash|max:30', 'media.*.license' => 'nullable|string|max:140', @@ -491,14 +475,14 @@ class ComposeController extends Controller // 'optimize_media' => 'nullable' ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); - if(config('costar.enabled') == true) { + if (config('costar.enabled') == true) { $blockedKeywords = config('costar.keyword.block'); - if($blockedKeywords !== null && $request->caption) { + if ($blockedKeywords !== null && $request->caption) { $keywords = config('costar.keyword.block'); - foreach($keywords as $kw) { - if(Str::contains($request->caption, $kw) == true) { + foreach ($keywords as $kw) { + if (Str::contains($request->caption, $kw) == true) { abort(400, 'Invalid object'); } } @@ -508,9 +492,9 @@ class ComposeController extends Controller $user = $request->user(); $profile = $user->profile; - $limitKey = 'compose:rate-limit:store:' . $user->id; + $limitKey = 'compose:rate-limit:store:'.$user->id; $limitTtl = now()->addMinutes(15); - $limitReached = Cache::remember($limitKey, $limitTtl, function() use($user) { + $limitReached = Cache::remember($limitKey, $limitTtl, function () use ($user) { $dailyLimit = Status::whereProfileId($user->profile_id) ->whereNull('in_reply_to_id') ->whereNull('reblog_of_id') @@ -534,12 +518,12 @@ class ComposeController extends Controller $tagged = $request->input('tagged'); $optimize_media = (bool) $request->input('optimize_media'); - foreach($medias as $k => $media) { - if($k + 1 > config_cache('pixelfed.max_album_length')) { + foreach ($medias as $k => $media) { + if ($k + 1 > config_cache('pixelfed.max_album_length')) { continue; } $m = Media::findOrFail($media['id']); - if($m->profile_id !== $profile->id || $m->status_id) { + if ($m->profile_id !== $profile->id || $m->status_id) { abort(403, 'Invalid media id'); } $m->filter_class = in_array($media['filter_class'], Filter::classes()) ? $media['filter_class'] : null; @@ -547,7 +531,7 @@ class ComposeController extends Controller $m->caption = isset($media['alt']) ? strip_tags($media['alt']) : null; $m->order = isset($media['cursor']) && is_int($media['cursor']) ? (int) $media['cursor'] : $k; - if($cw == true || $profile->cw == true) { + if ($cw == true || $profile->cw == true) { $m->is_nsfw = $cw; $status->is_nsfw = $cw; } @@ -560,19 +544,19 @@ class ComposeController extends Controller $mediaType = StatusController::mimeTypeCheck($mimes); - if(in_array($mediaType, ['photo', 'video', 'photo:album']) == false) { + if (in_array($mediaType, ['photo', 'video', 'photo:album']) == false) { abort(400, __('exception.compose.invalid.album')); } - if($place && is_array($place)) { + if ($place && is_array($place)) { $status->place_id = $place['id']; } - if($request->filled('comments_disabled')) { + if ($request->filled('comments_disabled')) { $status->comments_disabled = (bool) $request->input('comments_disabled'); } - if($request->filled('spoiler_text') && $cw) { + if ($request->filled('spoiler_text') && $cw) { $status->cw_summary = $request->input('spoiler_text'); } @@ -583,7 +567,7 @@ class ComposeController extends Controller $status->profile_id = $profile->id; $status->save(); - foreach($attachments as $media) { + foreach ($attachments as $media) { $media->status_id = $status->id; $media->save(); } @@ -597,7 +581,7 @@ class ComposeController extends Controller $status->type = $mediaType; $status->save(); - foreach($tagged as $tg) { + foreach ($tagged as $tg) { $mt = new MediaTag; $mt->status_id = $status->id; $mt->media_id = $status->media->first()->id; @@ -612,17 +596,17 @@ class ComposeController extends Controller MediaTagService::sendNotification($mt); } - if($request->filled('collections')) { + if ($request->filled('collections')) { $collections = Collection::whereProfileId($profile->id) ->find($request->input('collections')) - ->each(function($collection) use($status) { + ->each(function ($collection) use ($status) { $count = $collection->items()->count(); CollectionItem::firstOrCreate([ 'collection_id' => $collection->id, 'object_type' => 'App\Status', - 'object_id' => $status->id + 'object_id' => $status->id, ], [ - 'order' => $count + 'order' => $count, ]); CollectionService::addItem( @@ -643,7 +627,7 @@ class ComposeController extends Controller 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('profile:embed:'.$status->profile_id); Cache::forget($limitKey); return $status->url(); @@ -653,7 +637,7 @@ class ComposeController extends Controller { abort_unless(config('exp.top'), 404); $this->validate($request, [ - 'caption' => 'nullable|string|max:'.config('pixelfed.max_caption_length', 500), + 'caption' => 'nullable|string|max:'.config_cache('pixelfed.max_caption_length', 500), 'cw' => 'nullable|boolean', 'visibility' => 'required|string|in:public,private,unlisted|min:2|max:10', 'place' => 'nullable', @@ -661,14 +645,14 @@ class ComposeController extends Controller 'tagged' => 'nullable', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); - if(config('costar.enabled') == true) { + if (config('costar.enabled') == true) { $blockedKeywords = config('costar.keyword.block'); - if($blockedKeywords !== null && $request->caption) { + if ($blockedKeywords !== null && $request->caption) { $keywords = config('costar.keyword.block'); - foreach($keywords as $kw) { - if(Str::contains($request->caption, $kw) == true) { + foreach ($keywords as $kw) { + if (Str::contains($request->caption, $kw) == true) { abort(400, 'Invalid object'); } } @@ -683,11 +667,11 @@ class ComposeController extends Controller $cw = $request->input('cw'); $tagged = $request->input('tagged'); - if($place && is_array($place)) { + if ($place && is_array($place)) { $status->place_id = $place['id']; } - if($request->filled('comments_disabled')) { + if ($request->filled('comments_disabled')) { $status->comments_disabled = (bool) $request->input('comments_disabled'); } @@ -707,11 +691,11 @@ class ComposeController extends Controller 'bg_id' => 1, 'font_size' => strlen($status->caption) <= 140 ? 'h1' : 'h3', 'length' => strlen($status->caption), - ] + ], ], $entities), JSON_UNESCAPED_SLASHES); $status->save(); - foreach($tagged as $tg) { + foreach ($tagged as $tg) { $mt = new MediaTag; $mt->status_id = $status->id; $mt->media_id = $status->media->first()->id; @@ -726,7 +710,6 @@ class ComposeController extends Controller MediaTagService::sendNotification($mt); } - Cache::forget('user:account:id:'.$profile->user_id); Cache::forget('_api:statuses:recent_9:'.$profile->id); Cache::forget('profile:status_count:'.$profile->id); @@ -737,18 +720,18 @@ class ComposeController extends Controller public function mediaProcessingCheck(Request $request) { $this->validate($request, [ - 'id' => 'required|integer|min:1' + 'id' => 'required|integer|min:1', ]); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $media = Media::whereUserId($request->user()->id) ->whereNull('status_id') ->findOrFail($request->input('id')); - if(config('pixelfed.media_fast_process')) { + if (config('pixelfed.media_fast_process')) { return [ - 'finished' => true + 'finished' => true, ]; } @@ -762,27 +745,27 @@ class ComposeController extends Controller break; default: - # code... + // code... break; } return [ - 'finished' => $finished + 'finished' => $finished, ]; } public function composeSettings(Request $request) { $uid = $request->user()->id; - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); $default = [ 'default_license' => 1, 'media_descriptions' => false, - 'max_altext_length' => config_cache('pixelfed.max_altext_length') + 'max_altext_length' => config_cache('pixelfed.max_altext_length'), ]; $settings = AccountService::settings($uid); - if(isset($settings['other']) && isset($settings['other']['scope'])) { + if (isset($settings['other']) && isset($settings['other']['scope'])) { $s = $settings['compose_settings']; $s['default_scope'] = $settings['other']['scope']; $settings['compose_settings'] = $s; @@ -794,23 +777,22 @@ class ComposeController extends Controller public function createPoll(Request $request) { $this->validate($request, [ - 'caption' => 'nullable|string|max:'.config('pixelfed.max_caption_length', 500), + 'caption' => 'nullable|string|max:'.config_cache('pixelfed.max_caption_length', 500), 'cw' => 'nullable|boolean', 'visibility' => 'required|string|in:public,private', 'comments_disabled' => 'nullable', 'expiry' => 'required|in:60,360,1440,10080', - 'pollOptions' => 'required|array|min:1|max:4' + 'pollOptions' => 'required|array|min:1|max:4', ]); abort(404); abort_if(config('instance.polls.enabled') == false, 404, 'Polls not enabled'); - abort_if($request->user()->has_roles && !UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); + abort_if($request->user()->has_roles && ! UserRoleService::can('can-post', $request->user()->id), 403, 'Invalid permissions for this action'); abort_if(Status::whereType('poll') ->whereProfileId($request->user()->profile_id) ->whereCaption($request->input('caption')) ->where('created_at', '>', now()->subDays(2)) - ->exists() - , 422, 'Duplicate detected.'); + ->exists(), 422, 'Duplicate detected.'); $status = new Status; $status->profile_id = $request->user()->profile_id; @@ -827,7 +809,7 @@ class ComposeController extends Controller $poll->profile_id = $status->profile_id; $poll->poll_options = $request->input('pollOptions'); $poll->expires_at = now()->addMinutes($request->input('expiry')); - $poll->cached_tallies = collect($poll->poll_options)->map(function($o) { + $poll->cached_tallies = collect($poll->poll_options)->map(function ($o) { return 0; })->toArray(); $poll->save(); diff --git a/app/Services/ConfigCacheService.php b/app/Services/ConfigCacheService.php index bf34f5dcc..af2d1ef6a 100644 --- a/app/Services/ConfigCacheService.php +++ b/app/Services/ConfigCacheService.php @@ -75,6 +75,18 @@ class ConfigCacheService 'instance.curated_registration.enabled', 'federation.migration', + + 'pixelfed.max_caption_length', + 'pixelfed.max_bio_length', + 'pixelfed.max_name_length', + 'pixelfed.min_password_length', + 'pixelfed.max_avatar_size', + 'pixelfed.max_altext_length', + 'pixelfed.allow_app_registration', + 'pixelfed.app_registration_rate_limit_attempts', + 'pixelfed.app_registration_rate_limit_decay', + 'pixelfed.app_registration_confirm_rate_limit_attempts', + 'pixelfed.app_registration_confirm_rate_limit_decay', // 'system.user_mode' ]; diff --git a/app/Services/LandingService.php b/app/Services/LandingService.php index 199768b86..20759ecf4 100644 --- a/app/Services/LandingService.php +++ b/app/Services/LandingService.php @@ -2,105 +2,104 @@ namespace App\Services; -use App\Util\ActivityPub\Helpers; -use Illuminate\Support\Str; -use Illuminate\Support\Facades\Cache; -use Illuminate\Support\Facades\Redis; use App\Status; use App\User; -use App\Services\AccountService; use App\Util\Site\Nodeinfo; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Str; class LandingService { - public static function get($json = true) - { - $activeMonth = Nodeinfo::activeUsersMonthly(); + public static function get($json = true) + { + $activeMonth = Nodeinfo::activeUsersMonthly(); - $totalUsers = Cache::remember('api:nodeinfo:users', 43200, function() { - return User::count(); - }); + $totalUsers = Cache::remember('api:nodeinfo:users', 43200, function () { + return User::count(); + }); - $postCount = Cache::remember('api:nodeinfo:statuses', 21600, function() { - return Status::whereLocal(true)->count(); - }); + $postCount = Cache::remember('api:nodeinfo:statuses', 21600, function () { + return Status::whereLocal(true)->count(); + }); - $contactAccount = Cache::remember('api:v1:instance-data:contact', 604800, function () { - if(config_cache('instance.admin.pid')) { - return AccountService::getMastodon(config_cache('instance.admin.pid'), true); - } - $admin = User::whereIsAdmin(true)->first(); - return $admin && isset($admin->profile_id) ? - AccountService::getMastodon($admin->profile_id, true) : - null; - }); + $contactAccount = Cache::remember('api:v1:instance-data:contact', 604800, function () { + if (config_cache('instance.admin.pid')) { + return AccountService::getMastodon(config_cache('instance.admin.pid'), true); + } + $admin = User::whereIsAdmin(true)->first(); - $rules = Cache::remember('api:v1:instance-data:rules', 604800, function () { - return config_cache('app.rules') ? - collect(json_decode(config_cache('app.rules'), true)) - ->map(function($rule, $key) { - $id = $key + 1; - return [ - 'id' => "{$id}", - 'text' => $rule - ]; - }) - ->toArray() : []; - }); + return $admin && isset($admin->profile_id) ? + AccountService::getMastodon($admin->profile_id, true) : + null; + }); - $openReg = (bool) config_cache('pixelfed.open_registration'); + $rules = Cache::remember('api:v1:instance-data:rules', 604800, function () { + return config_cache('app.rules') ? + collect(json_decode(config_cache('app.rules'), true)) + ->map(function ($rule, $key) { + $id = $key + 1; - $res = [ - 'name' => config_cache('app.name'), - 'url' => config_cache('app.url'), - 'domain' => config('pixelfed.domain.app'), - 'show_directory' => config_cache('instance.landing.show_directory'), - 'show_explore_feed' => config_cache('instance.landing.show_explore'), - 'open_registration' => (bool) $openReg, - 'curated_onboarding' => (bool) config_cache('instance.curated_registration.enabled'), - 'version' => config('pixelfed.version'), - 'about' => [ - 'banner_image' => config_cache('app.banner_image') ?? url('/storage/headers/default.jpg'), - 'short_description' => config_cache('app.short_description'), - 'description' => config_cache('app.description'), - ], - 'stats' => [ - 'active_users' => (int) $activeMonth, - 'posts_count' => (int) $postCount, - 'total_users' => (int) $totalUsers - ], - 'contact' => [ - 'account' => $contactAccount, - 'email' => config('instance.email') - ], - 'rules' => $rules, - 'uploader' => [ - 'max_photo_size' => (int) (config('pixelfed.max_photo_size') * 1024), - 'max_caption_length' => (int) config('pixelfed.max_caption_length'), - 'max_altext_length' => (int) config('pixelfed.max_altext_length', 150), - 'album_limit' => (int) config_cache('pixelfed.max_album_length'), - 'image_quality' => (int) config_cache('pixelfed.image_quality'), - 'max_collection_length' => (int) config('pixelfed.max_collection_length', 18), - 'optimize_image' => (bool) config('pixelfed.optimize_image'), - 'optimize_video' => (bool) config('pixelfed.optimize_video'), - 'media_types' => config_cache('pixelfed.media_types'), - ], - 'features' => [ - 'federation' => config_cache('federation.activitypub.enabled'), - 'timelines' => [ - 'local' => true, - 'network' => (bool) config('federation.network_timeline'), - ], - 'mobile_apis' => (bool) config_cache('pixelfed.oauth_enabled'), - 'stories' => (bool) config_cache('instance.stories.enabled'), - 'video' => Str::contains(config_cache('pixelfed.media_types'), 'video/mp4'), - ] - ]; + return [ + 'id' => "{$id}", + 'text' => $rule, + ]; + }) + ->toArray() : []; + }); - if($json) { - return json_encode($res); - } + $openReg = (bool) config_cache('pixelfed.open_registration'); - return $res; - } + $res = [ + 'name' => config_cache('app.name'), + 'url' => config_cache('app.url'), + 'domain' => config('pixelfed.domain.app'), + 'show_directory' => config_cache('instance.landing.show_directory'), + 'show_explore_feed' => config_cache('instance.landing.show_explore'), + 'open_registration' => (bool) $openReg, + 'curated_onboarding' => (bool) config_cache('instance.curated_registration.enabled'), + 'version' => config('pixelfed.version'), + 'about' => [ + 'banner_image' => config_cache('app.banner_image') ?? url('/storage/headers/default.jpg'), + 'short_description' => config_cache('app.short_description'), + 'description' => config_cache('app.description'), + ], + 'stats' => [ + 'active_users' => (int) $activeMonth, + 'posts_count' => (int) $postCount, + 'total_users' => (int) $totalUsers, + ], + 'contact' => [ + 'account' => $contactAccount, + 'email' => config('instance.email'), + ], + 'rules' => $rules, + 'uploader' => [ + 'max_photo_size' => (int) (config_cache('pixelfed.max_photo_size') * 1024), + 'max_caption_length' => (int) config_cache('pixelfed.max_caption_length'), + 'max_altext_length' => (int) config_cache('pixelfed.max_altext_length', 150), + 'album_limit' => (int) config_cache('pixelfed.max_album_length'), + 'image_quality' => (int) config_cache('pixelfed.image_quality'), + 'max_collection_length' => (int) config('pixelfed.max_collection_length', 18), + 'optimize_image' => (bool) config_cache('pixelfed.optimize_image'), + 'optimize_video' => (bool) config_cache('pixelfed.optimize_video'), + 'media_types' => config_cache('pixelfed.media_types'), + ], + 'features' => [ + 'federation' => config_cache('federation.activitypub.enabled'), + 'timelines' => [ + 'local' => true, + 'network' => (bool) config_cache('federation.network_timeline'), + ], + 'mobile_apis' => (bool) config_cache('pixelfed.oauth_enabled'), + 'stories' => (bool) config_cache('instance.stories.enabled'), + 'video' => Str::contains(config_cache('pixelfed.media_types'), 'video/mp4'), + ], + ]; + + if ($json) { + return json_encode($res); + } + + return $res; + } } diff --git a/app/Util/Site/Config.php b/app/Util/Site/Config.php index e0916591d..46af16a42 100644 --- a/app/Util/Site/Config.php +++ b/app/Util/Site/Config.php @@ -5,31 +5,33 @@ namespace App\Util\Site; use Cache; use Illuminate\Support\Str; -class Config { - +class Config +{ const CACHE_KEY = 'api:site:configuration:_v0.8'; - public static function get() { - return Cache::remember(self::CACHE_KEY, 900, function() { + public static function get() + { + return Cache::remember(self::CACHE_KEY, 900, function () { $hls = [ 'enabled' => config('media.hls.enabled'), ]; - if(config('media.hls.enabled')) { + if (config('media.hls.enabled')) { $hls = [ 'enabled' => true, 'debug' => (bool) config('media.hls.debug'), 'p2p' => (bool) config('media.hls.p2p'), 'p2p_debug' => (bool) config('media.hls.p2p_debug'), 'tracker' => config('media.hls.tracker'), - 'ice' => config('media.hls.ice') + 'ice' => config('media.hls.ice'), ]; } + return [ 'version' => config('pixelfed.version'), 'open_registration' => (bool) config_cache('pixelfed.open_registration'), 'uploader' => [ 'max_photo_size' => (int) config('pixelfed.max_photo_size'), - 'max_caption_length' => (int) config('pixelfed.max_caption_length'), + 'max_caption_length' => (int) config_cache('pixelfed.max_caption_length'), 'max_altext_length' => (int) config('pixelfed.max_altext_length', 150), 'album_limit' => (int) config_cache('pixelfed.max_album_length'), 'image_quality' => (int) config_cache('pixelfed.image_quality'), @@ -41,12 +43,12 @@ class Config { 'media_types' => config_cache('pixelfed.media_types'), 'mime_types' => config_cache('pixelfed.media_types') ? explode(',', config_cache('pixelfed.media_types')) : [], - 'enforce_account_limit' => (bool) config_cache('pixelfed.enforce_account_limit') + 'enforce_account_limit' => (bool) config_cache('pixelfed.enforce_account_limit'), ], 'activitypub' => [ 'enabled' => (bool) config_cache('federation.activitypub.enabled'), - 'remote_follow' => config('federation.activitypub.remoteFollow') + 'remote_follow' => config('federation.activitypub.remoteFollow'), ], 'ab' => config('exp'), @@ -54,8 +56,8 @@ class Config { 'site' => [ 'name' => config_cache('app.name'), 'domain' => config('pixelfed.domain.app'), - 'url' => config('app.url'), - 'description' => config_cache('app.short_description') + 'url' => config('app.url'), + 'description' => config_cache('app.short_description'), ], 'account' => [ @@ -63,15 +65,15 @@ class Config { 'max_bio_length' => config('pixelfed.max_bio_length'), 'max_name_length' => config('pixelfed.max_name_length'), 'min_password_length' => config('pixelfed.min_password_length'), - 'max_account_size' => config('pixelfed.max_account_size') + 'max_account_size' => config('pixelfed.max_account_size'), ], 'username' => [ 'remote' => [ 'formats' => config('instance.username.remote.formats'), 'format' => config('instance.username.remote.format'), - 'custom' => config('instance.username.remote.custom') - ] + 'custom' => config('instance.username.remote.custom'), + ], ], 'features' => [ @@ -85,22 +87,23 @@ class Config { 'import' => [ 'instagram' => (bool) config_cache('pixelfed.import.instagram.enabled'), 'mastodon' => false, - 'pixelfed' => false + 'pixelfed' => false, ], 'label' => [ 'covid' => [ 'enabled' => (bool) config('instance.label.covid.enabled'), 'org' => config('instance.label.covid.org'), 'url' => config('instance.label.covid.url'), - ] + ], ], - 'hls' => $hls - ] + 'hls' => $hls, + ], ]; }); } - public static function json() { + public static function json() + { return json_encode(self::get(), JSON_FORCE_OBJECT); } } diff --git a/resources/views/site/help/sharing-media.blade.php b/resources/views/site/help/sharing-media.blade.php index d429f7406..3fe275d39 100644 --- a/resources/views/site/help/sharing-media.blade.php +++ b/resources/views/site/help/sharing-media.blade.php @@ -50,7 +50,7 @@
- During the compose process, you will see the Caption input. Captions are optional and limited to {{config('pixelfed.max_caption_length')}} characters. + During the compose process, you will see the Caption input. Captions are optional and limited to {{config_cache('pixelfed.max_caption_length')}} characters.