Update cloud storage, use config_cache

This commit is contained in:
Daniel Supernault 2024-03-12 01:03:33 -06:00
parent a72188a7db
commit 665581d80c
No known key found for this signature in database
GPG key ID: 23740873EE6F76A1
20 changed files with 669 additions and 673 deletions

View file

@ -82,7 +82,7 @@ class AvatarStorage extends Command
$this->line(' '); $this->line(' ');
if(config_cache('pixelfed.cloud_storage')) { if((bool) config_cache('pixelfed.cloud_storage')) {
$this->info('✅ - Cloud storage configured'); $this->info('✅ - Cloud storage configured');
$this->line(' '); $this->line(' ');
} }
@ -92,7 +92,7 @@ class AvatarStorage extends Command
$this->line(' '); $this->line(' ');
} }
if(config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud')) { if((bool) config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud')) {
$disk = Storage::disk(config_cache('filesystems.cloud')); $disk = Storage::disk(config_cache('filesystems.cloud'));
$exists = $disk->exists('cache/avatars/default.jpg'); $exists = $disk->exists('cache/avatars/default.jpg');
$state = $exists ? '✅' : '❌'; $state = $exists ? '✅' : '❌';
@ -100,7 +100,7 @@ class AvatarStorage extends Command
$this->info($msg); $this->info($msg);
} }
$options = config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud') ? $options = (bool) config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud') ?
[ [
'Cancel', 'Cancel',
'Upload default avatar to cloud', 'Upload default avatar to cloud',
@ -164,7 +164,7 @@ class AvatarStorage extends Command
protected function uploadAvatarsToCloud() protected function uploadAvatarsToCloud()
{ {
if(!config_cache('pixelfed.cloud_storage') || !config('instance.avatar.local_to_cloud')) { if(!(bool) config_cache('pixelfed.cloud_storage') || !config('instance.avatar.local_to_cloud')) {
$this->error('Enable cloud storage and avatar cloud storage to perform this action'); $this->error('Enable cloud storage and avatar cloud storage to perform this action');
return; return;
} }
@ -213,7 +213,7 @@ class AvatarStorage extends Command
return; return;
} }
if(config_cache('pixelfed.cloud_storage') == false && config_cache('federation.avatars.store_local') == false) { if((bool) config_cache('pixelfed.cloud_storage') == false && config_cache('federation.avatars.store_local') == false) {
$this->error('You have cloud storage disabled and local avatar storage disabled, we cannot refetch avatars.'); $this->error('You have cloud storage disabled and local avatar storage disabled, we cannot refetch avatars.');
return; return;
} }

View file

@ -44,7 +44,7 @@ class AvatarStorageDeepClean extends Command
$this->line(' '); $this->line(' ');
$storage = [ $storage = [
'cloud' => boolval(config_cache('pixelfed.cloud_storage')), 'cloud' => (bool) config_cache('pixelfed.cloud_storage'),
'local' => boolval(config_cache('federation.avatars.store_local')) 'local' => boolval(config_cache('federation.avatars.store_local'))
]; ];

View file

@ -35,12 +35,16 @@ class CloudMediaMigrate extends Command
*/ */
public function handle() public function handle()
{ {
$enabled = config('pixelfed.cloud_storage'); $enabled = (bool) config_cache('pixelfed.cloud_storage');
if(!$enabled) { if(!$enabled) {
$this->error('Cloud storage not enabled. Exiting...'); $this->error('Cloud storage not enabled. Exiting...');
return; return;
} }
if(!$this->confirm('Are you sure you want to proceed?')) {
return;
}
$limit = $this->option('limit'); $limit = $this->option('limit');
$hugeMode = $this->option('huge'); $hugeMode = $this->option('huge');

View file

@ -37,7 +37,7 @@ class FixMediaDriver extends Command
return Command::SUCCESS; return Command::SUCCESS;
} }
if(config_cache('pixelfed.cloud_storage') == false) { if((bool) config_cache('pixelfed.cloud_storage') == false) {
$this->error('Cloud storage not enabled, exiting...'); $this->error('Cloud storage not enabled, exiting...');
return Command::SUCCESS; return Command::SUCCESS;
} }

View file

@ -47,7 +47,7 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
protected function preflightCheck() protected function preflightCheck()
{ {
if(config_cache('pixelfed.cloud_storage') != true) { if(!(bool) config_cache('pixelfed.cloud_storage')) {
$this->info('Error: Cloud storage is not enabled!'); $this->info('Error: Cloud storage is not enabled!');
$this->error('Aborting...'); $this->error('Aborting...');
exit; exit;

View file

@ -45,7 +45,7 @@ class MediaS3GarbageCollector extends Command
*/ */
public function handle() public function handle()
{ {
$enabled = in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']); $enabled = (bool) config_cache('pixelfed.cloud_storage');
if(!$enabled) { if(!$enabled) {
$this->error('Cloud storage not enabled. Exiting...'); $this->error('Cloud storage not enabled. Exiting...');
return; return;

View file

@ -33,7 +33,7 @@ class Kernel extends ConsoleKernel
$schedule->command('gc:passwordreset')->dailyAt('09:41')->onOneServer(); $schedule->command('gc:passwordreset')->dailyAt('09:41')->onOneServer();
$schedule->command('gc:sessions')->twiceDaily(13, 23)->onOneServer(); $schedule->command('gc:sessions')->twiceDaily(13, 23)->onOneServer();
if (in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']) && config('media.delete_local_after_cloud')) { if ((bool) config_cache('pixelfed.cloud_storage') && (bool) config_cache('media.delete_local_after_cloud')) {
$schedule->command('media:s3gc')->hourlyAt(15); $schedule->command('media:s3gc')->hourlyAt(15);
} }

View file

@ -741,7 +741,7 @@ class ComposeController extends Controller
case 'image/jpeg': case 'image/jpeg':
case 'image/png': case 'image/png':
case 'video/mp4': case 'video/mp4':
$finished = config_cache('pixelfed.cloud_storage') ? (bool) $media->cdn_url : (bool) $media->processed_at; $finished = (bool) config_cache('pixelfed.cloud_storage') ? (bool) $media->cdn_url : (bool) $media->processed_at;
break; break;
default: default:

View file

@ -2,14 +2,15 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Media; use App\Media;
use Illuminate\Http\Request;
class MediaController extends Controller class MediaController extends Controller
{ {
public function index(Request $request) public function index(Request $request)
{ {
//return view('settings.drive.index'); //return view('settings.drive.index');
abort(404);
} }
public function composeUpdate(Request $request, $id) public function composeUpdate(Request $request, $id)
@ -19,7 +20,7 @@ class MediaController extends Controller
public function fallbackRedirect(Request $request, $pid, $mhash, $uhash, $f) public function fallbackRedirect(Request $request, $pid, $mhash, $uhash, $f)
{ {
abort_if(!config_cache('pixelfed.cloud_storage'), 404); abort_if(! (bool) config_cache('pixelfed.cloud_storage'), 404);
$path = 'public/m/_v2/'.$pid.'/'.$mhash.'/'.$uhash.'/'.$f; $path = 'public/m/_v2/'.$pid.'/'.$mhash.'/'.$uhash.'/'.$f;
$media = Media::whereProfileId($pid) $media = Media::whereProfileId($pid)
->whereMediaPath($path) ->whereMediaPath($path)

View file

@ -2,22 +2,20 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Services\Account\RemoteAuthService;
use App\Models\RemoteAuth; use App\Models\RemoteAuth;
use App\Profile; use App\Services\Account\RemoteAuthService;
use App\Instance;
use App\User;
use Purify;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Auth\Events\Registered;
use App\Util\Lexer\RestrictedNames;
use App\Services\EmailService; use App\Services\EmailService;
use App\Services\MediaStorageService; use App\Services\MediaStorageService;
use App\User;
use App\Util\ActivityPub\Helpers; use App\Util\ActivityPub\Helpers;
use App\Util\Lexer\RestrictedNames;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use InvalidArgumentException; use InvalidArgumentException;
use Purify;
class RemoteAuthController extends Controller class RemoteAuthController extends Controller
{ {
@ -33,6 +31,7 @@ class RemoteAuthController extends Controller
if ($request->user()) { if ($request->user()) {
return redirect('/'); return redirect('/');
} }
return view('auth.remote.start'); return view('auth.remote.start');
} }
@ -57,6 +56,7 @@ class RemoteAuthController extends Controller
return []; return [];
} }
$res = explode(',', $res); $res = explode(',', $res);
return response()->json($res); return response()->json($res);
} }
@ -70,6 +70,7 @@ class RemoteAuthController extends Controller
return []; return [];
} }
$res = explode(',', $res); $res = explode(',', $res);
return response()->json($res); return response()->json($res);
} }
@ -97,8 +98,9 @@ class RemoteAuthController extends Controller
$res = [ $res = [
'domain' => $domain, 'domain' => $domain,
'ready' => false, 'ready' => false,
'action' => 'incompatible_domain' 'action' => 'incompatible_domain',
]; ];
return response()->json($res); return response()->json($res);
} }
@ -108,8 +110,9 @@ class RemoteAuthController extends Controller
$res = [ $res = [
'domain' => $domain, 'domain' => $domain,
'ready' => false, 'ready' => false,
'action' => 'blocked_domain' 'action' => 'blocked_domain',
]; ];
return response()->json($res); return response()->json($res);
} }
@ -119,8 +122,9 @@ class RemoteAuthController extends Controller
$res = [ $res = [
'domain' => $domain, 'domain' => $domain,
'ready' => false, 'ready' => false,
'action' => 'incompatible_domain' 'action' => 'incompatible_domain',
]; ];
return response()->json($res); return response()->json($res);
} }
@ -130,8 +134,9 @@ class RemoteAuthController extends Controller
$res = [ $res = [
'domain' => $domain, 'domain' => $domain,
'ready' => false, 'ready' => false,
'action' => 'incompatible_domain' 'action' => 'incompatible_domain',
]; ];
return response()->json($res); return response()->json($res);
} }
} }
@ -142,8 +147,9 @@ class RemoteAuthController extends Controller
$res = [ $res = [
'domain' => $domain, 'domain' => $domain,
'ready' => false, 'ready' => false,
'action' => 'incompatible_domain' 'action' => 'incompatible_domain',
]; ];
return response()->json($res); return response()->json($res);
} }
} }
@ -169,7 +175,7 @@ class RemoteAuthController extends Controller
$res = [ $res = [
'domain' => $domain, 'domain' => $domain,
'ready' => true, 'ready' => true,
'dsh' => $dsh 'dsh' => $dsh,
]; ];
return response()->json($res); return response()->json($res);
@ -218,10 +224,12 @@ class RemoteAuthController extends Controller
if (! $res || ! isset($res['access_token'])) { if (! $res || ! isset($res['access_token'])) {
$request->session()->regenerate(); $request->session()->regenerate();
return redirect('/login'); return redirect('/login');
} }
$request->session()->put('oauth_remote_session_token', $res['access_token']); $request->session()->put('oauth_remote_session_token', $res['access_token']);
return redirect('/auth/mastodon/getting-started'); return redirect('/auth/mastodon/getting-started');
} }
@ -240,6 +248,7 @@ class RemoteAuthController extends Controller
if ($request->user()) { if ($request->user()) {
return redirect('/'); return redirect('/');
} }
return view('auth.remote.onboarding'); return view('auth.remote.onboarding');
} }
@ -273,7 +282,7 @@ class RemoteAuthController extends Controller
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'msg' => 'Success!', 'msg' => 'Success!',
'action' => 'max_uses_reached' 'action' => 'max_uses_reached',
]); ]);
} }
} }
@ -283,14 +292,14 @@ class RemoteAuthController extends Controller
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'msg' => 'Success!', 'msg' => 'Success!',
'action' => 'redirect_existing_user' 'action' => 'redirect_existing_user',
]); ]);
} }
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'msg' => 'Success!', 'msg' => 'Success!',
'action' => 'onboard' 'action' => 'onboard',
]); ]);
} }
@ -324,7 +333,7 @@ class RemoteAuthController extends Controller
'bearer_token' => $token, 'bearer_token' => $token,
'verify_credentials' => $res, 'verify_credentials' => $res,
'last_verify_credentials_at' => now(), 'last_verify_credentials_at' => now(),
'last_successful_login_at' => now() 'last_successful_login_at' => now(),
]); ]);
$request->session()->put('oauth_masto_raid', $ra->id); $request->session()->put('oauth_masto_raid', $ra->id);
@ -380,8 +389,8 @@ class RemoteAuthController extends Controller
if (in_array(strtolower($value), array_map('strtolower', $restricted))) { if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
return $fail('Username cannot be used.'); return $fail('Username cannot be used.');
} }
} },
] ],
]); ]);
$username = strtolower($request->input('username')); $username = strtolower($request->input('username'));
@ -390,7 +399,7 @@ class RemoteAuthController extends Controller
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'username' => $username, 'username' => $username,
'exists' => $exists 'exists' => $exists,
]); ]);
} }
@ -411,7 +420,7 @@ class RemoteAuthController extends Controller
'email' => [ 'email' => [
'required', 'required',
'email:strict,filter_unicode,dns,spoof', 'email:strict,filter_unicode,dns,spoof',
] ],
]); ]);
$email = $request->input('email'); $email = $request->input('email');
@ -422,7 +431,7 @@ class RemoteAuthController extends Controller
'code' => 200, 'code' => 200,
'email' => $email, 'email' => $email,
'exists' => $exists, 'exists' => $exists,
'banned' => $banned 'banned' => $banned,
]); ]);
} }
@ -448,7 +457,7 @@ class RemoteAuthController extends Controller
if (! $res) { if (! $res) {
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'following' => [] 'following' => [],
]); ]);
} }
@ -456,7 +465,7 @@ class RemoteAuthController extends Controller
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'following' => $res 'following' => $res,
]); ]);
} }
@ -512,10 +521,10 @@ class RemoteAuthController extends Controller
if (in_array(strtolower($value), array_map('strtolower', $restricted))) { if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
return $fail('Username cannot be used.'); return $fail('Username cannot be used.');
} }
} },
], ],
'password' => 'required|string|min:8|confirmed', 'password' => 'required|string|min:8|confirmed',
'name' => 'nullable|max:30' 'name' => 'nullable|max:30',
]); ]);
$email = $request->input('email'); $email = $request->input('email');
@ -527,7 +536,7 @@ class RemoteAuthController extends Controller
'name' => $name, 'name' => $name,
'username' => $username, 'username' => $username,
'password' => $password, 'password' => $password,
'email' => $email 'email' => $email,
]); ]);
$raid = $request->session()->pull('oauth_masto_raid'); $raid = $request->session()->pull('oauth_masto_raid');
@ -541,7 +550,7 @@ class RemoteAuthController extends Controller
return [ return [
'code' => 200, 'code' => 200,
'msg' => 'Success', 'msg' => 'Success',
'token' => $token 'token' => $token,
]; ];
} }
@ -585,7 +594,7 @@ class RemoteAuthController extends Controller
abort_unless($request->session()->exists('oauth_remasto_id'), 403); abort_unless($request->session()->exists('oauth_remasto_id'), 403);
$this->validate($request, [ $this->validate($request, [
'account' => 'required|url' 'account' => 'required|url',
]); ]);
$account = $request->input('account'); $account = $request->input('account');
@ -641,7 +650,7 @@ class RemoteAuthController extends Controller
$avatar->remote_url = $request->input('avatar_url'); $avatar->remote_url = $request->input('avatar_url');
$avatar->save(); $avatar->save();
MediaStorageService::avatar($avatar, config_cache('pixelfed.cloud_storage') == false); MediaStorageService::avatar($avatar, (bool) config_cache('pixelfed.cloud_storage') == false);
return [200]; return [200];
} }
@ -691,6 +700,7 @@ class RemoteAuthController extends Controller
$user = User::findOrFail($ra->user_id); $user = User::findOrFail($ra->user_id);
abort_if($user->is_admin || $user->status != null, 422, 'Invalid auth action'); abort_if($user->is_admin || $user->status != null, 422, 'Invalid auth action');
Auth::loginUsingId($ra->user_id); Auth::loginUsingId($ra->user_id);
return [200]; return [200];
} }
@ -703,7 +713,7 @@ class RemoteAuthController extends Controller
'password' => Hash::make($data['password']), 'password' => Hash::make($data['password']),
'email_verified_at' => config('remote-auth.mastodon.contraints.skip_email_verification') ? now() : null, 'email_verified_at' => config('remote-auth.mastodon.contraints.skip_email_verification') ? now() : null,
'app_register_ip' => request()->ip(), 'app_register_ip' => request()->ip(),
'register_source' => 'mastodon' 'register_source' => 'mastodon',
]))); ])));
$this->guarder()->login($user); $this->guarder()->login($user);

View file

@ -2,9 +2,9 @@
namespace App\Jobs\AvatarPipeline; namespace App\Jobs\AvatarPipeline;
use Cache;
use App\Avatar; use App\Avatar;
use App\Profile; use App\Profile;
use Cache;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -20,6 +20,7 @@ class AvatarOptimize implements ShouldQueue
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $profile; protected $profile;
protected $current; protected $current;
/** /**
@ -65,7 +66,7 @@ class AvatarOptimize implements ShouldQueue
Cache::forget('avatar:'.$avatar->profile_id); Cache::forget('avatar:'.$avatar->profile_id);
$this->deleteOldAvatar($avatar->media_path, $this->current); $this->deleteOldAvatar($avatar->media_path, $this->current);
if(config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud')) { if ((bool) config_cache('pixelfed.cloud_storage') && (bool) config_cache('instance.avatar.local_to_cloud')) {
$this->uploadToCloud($avatar); $this->uploadToCloud($avatar);
} else { } else {
$avatar->cdn_url = null; $avatar->cdn_url = null;
@ -79,8 +80,7 @@ class AvatarOptimize implements ShouldQueue
{ {
if (storage_path('app/'.$new) == $current || if (storage_path('app/'.$new) == $current ||
Str::endsWith($current, 'avatars/default.png') || Str::endsWith($current, 'avatars/default.png') ||
Str::endsWith($current, 'avatars/default.jpg')) Str::endsWith($current, 'avatars/default.jpg')) {
{
return; return;
} }
if (is_file($current)) { if (is_file($current)) {

View file

@ -4,20 +4,13 @@ namespace App\Jobs\AvatarPipeline;
use App\Avatar; use App\Avatar;
use App\Profile; use App\Profile;
use App\Services\MediaStorageService;
use App\Util\ActivityPub\Helpers;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use App\Util\ActivityPub\Helpers;
use Illuminate\Support\Str;
use Zttp\Zttp;
use App\Http\Controllers\AvatarController;
use Storage;
use Log;
use Illuminate\Http\File;
use App\Services\MediaStorageService;
use App\Services\ActivityPubFetchService;
class RemoteAvatarFetch implements ShouldQueue class RemoteAvatarFetch implements ShouldQueue
{ {
@ -38,7 +31,9 @@ class RemoteAvatarFetch implements ShouldQueue
* @var int * @var int
*/ */
public $tries = 1; public $tries = 1;
public $timeout = 300; public $timeout = 300;
public $maxExceptions = 1; public $maxExceptions = 1;
/** /**
@ -60,7 +55,7 @@ class RemoteAvatarFetch implements ShouldQueue
{ {
$profile = $this->profile; $profile = $this->profile;
if(boolval(config_cache('pixelfed.cloud_storage')) == false && boolval(config_cache('federation.avatars.store_local')) == false) { if ((bool) config_cache('pixelfed.cloud_storage') == false && (bool) config_cache('federation.avatars.store_local') == false) {
return 1; return 1;
} }
@ -108,7 +103,7 @@ class RemoteAvatarFetch implements ShouldQueue
$avatar->remote_url = $icon['url']; $avatar->remote_url = $icon['url'];
$avatar->save(); $avatar->save();
MediaStorageService::avatar($avatar, boolval(config_cache('pixelfed.cloud_storage')) == false, true); MediaStorageService::avatar($avatar, (bool) config_cache('pixelfed.cloud_storage') == false, true);
return 1; return 1;
} }

View file

@ -4,28 +4,21 @@ namespace App\Jobs\AvatarPipeline;
use App\Avatar; use App\Avatar;
use App\Profile; use App\Profile;
use App\Services\AccountService;
use App\Services\MediaStorageService;
use Cache;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use App\Util\ActivityPub\Helpers;
use Illuminate\Support\Str;
use Zttp\Zttp;
use App\Http\Controllers\AvatarController;
use Cache;
use Storage;
use Log;
use Illuminate\Http\File;
use App\Services\AccountService;
use App\Services\MediaStorageService;
use App\Services\ActivityPubFetchService;
class RemoteAvatarFetchFromUrl implements ShouldQueue class RemoteAvatarFetchFromUrl implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $profile; protected $profile;
protected $url; protected $url;
/** /**
@ -41,7 +34,9 @@ class RemoteAvatarFetchFromUrl implements ShouldQueue
* @var int * @var int
*/ */
public $tries = 1; public $tries = 1;
public $timeout = 300; public $timeout = 300;
public $maxExceptions = 1; public $maxExceptions = 1;
/** /**
@ -67,7 +62,7 @@ class RemoteAvatarFetchFromUrl implements ShouldQueue
Cache::forget('avatar:'.$profile->id); Cache::forget('avatar:'.$profile->id);
AccountService::del($profile->id); AccountService::del($profile->id);
if(boolval(config_cache('pixelfed.cloud_storage')) == false && boolval(config_cache('federation.avatars.store_local')) == false) { if ((bool) config_cache('pixelfed.cloud_storage') == false && (bool) config_cache('federation.avatars.store_local') == false) {
return 1; return 1;
} }
@ -89,7 +84,7 @@ class RemoteAvatarFetchFromUrl implements ShouldQueue
$avatar->save(); $avatar->save();
} }
MediaStorageService::avatar($avatar, boolval(config_cache('pixelfed.cloud_storage')) == false, true); MediaStorageService::avatar($avatar, (bool) config_cache('pixelfed.cloud_storage') == false, true);
return 1; return 1;
} }

View file

@ -3,27 +3,30 @@
namespace App\Jobs\MediaPipeline; namespace App\Jobs\MediaPipeline;
use App\Media; use App\Media;
use App\Services\Media\MediaHlsService;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage;
use App\Services\Media\MediaHlsService;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
class MediaDeletePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing class MediaDeletePipeline implements ShouldBeUniqueUntilProcessing, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $media; protected $media;
public $timeout = 300; public $timeout = 300;
public $tries = 3; public $tries = 3;
public $maxExceptions = 1; public $maxExceptions = 1;
public $failOnTimeout = true; public $failOnTimeout = true;
public $deleteWhenMissingModels = true; public $deleteWhenMissingModels = true;
/** /**
@ -70,7 +73,7 @@ class MediaDeletePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing
array_pop($e); array_pop($e);
$i = implode('/', $e); $i = implode('/', $e);
if(config_cache('pixelfed.cloud_storage') == true) { if ((bool) config_cache('pixelfed.cloud_storage') == true) {
$disk = Storage::disk(config('filesystems.cloud')); $disk = Storage::disk(config('filesystems.cloud'));
if ($path && $disk->exists($path)) { if ($path && $disk->exists($path)) {

View file

@ -8,7 +8,6 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
class MediaFixLocalFilesystemCleanupPipeline implements ShouldQueue class MediaFixLocalFilesystemCleanupPipeline implements ShouldQueue
@ -16,12 +15,14 @@ class MediaFixLocalFilesystemCleanupPipeline implements ShouldQueue
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 1800; public $timeout = 1800;
public $tries = 5; public $tries = 5;
public $maxExceptions = 1; public $maxExceptions = 1;
public function handle() public function handle()
{ {
if(config_cache('pixelfed.cloud_storage') == false) { if ((bool) config_cache('pixelfed.cloud_storage') == false) {
// Only run if cloud storage is enabled // Only run if cloud storage is enabled
return; return;
} }

View file

@ -3,9 +3,9 @@
namespace App\Observers; namespace App\Observers;
use App\Avatar; use App\Avatar;
use App\Services\AccountService;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Services\AccountService;
class AvatarObserver class AvatarObserver
{ {
@ -19,7 +19,6 @@ class AvatarObserver
/** /**
* Handle the avatar "created" event. * Handle the avatar "created" event.
* *
* @param \App\Avatar $avatar
* @return void * @return void
*/ */
public function created(Avatar $avatar) public function created(Avatar $avatar)
@ -30,7 +29,6 @@ class AvatarObserver
/** /**
* Handle the avatar "updated" event. * Handle the avatar "updated" event.
* *
* @param \App\Avatar $avatar
* @return void * @return void
*/ */
public function updated(Avatar $avatar) public function updated(Avatar $avatar)
@ -41,7 +39,6 @@ class AvatarObserver
/** /**
* Handle the avatar "deleted" event. * Handle the avatar "deleted" event.
* *
* @param \App\Avatar $avatar
* @return void * @return void
*/ */
public function deleted(Avatar $avatar) public function deleted(Avatar $avatar)
@ -52,7 +49,6 @@ class AvatarObserver
/** /**
* Handle the avatar "deleting" event. * Handle the avatar "deleting" event.
* *
* @param \App\Avatar $avatar
* @return void * @return void
*/ */
public function deleting(Avatar $avatar) public function deleting(Avatar $avatar)
@ -65,7 +61,7 @@ class AvatarObserver
@unlink($path); @unlink($path);
} }
if(config_cache('pixelfed.cloud_storage')) { if ((bool) config_cache('pixelfed.cloud_storage')) {
$disk = Storage::disk(config('filesystems.cloud')); $disk = Storage::disk(config('filesystems.cloud'));
$base = Str::startsWith($avatar->media_path, 'cache/avatars/'); $base = Str::startsWith($avatar->media_path, 'cache/avatars/');
if ($base && $disk->exists($avatar->media_path)) { if ($base && $disk->exists($avatar->media_path)) {
@ -78,7 +74,6 @@ class AvatarObserver
/** /**
* Handle the avatar "restored" event. * Handle the avatar "restored" event.
* *
* @param \App\Avatar $avatar
* @return void * @return void
*/ */
public function restored(Avatar $avatar) public function restored(Avatar $avatar)
@ -89,7 +84,6 @@ class AvatarObserver
/** /**
* Handle the avatar "force deleted" event. * Handle the avatar "force deleted" event.
* *
* @param \App\Avatar $avatar
* @return void * @return void
*/ */
public function forceDeleted(Avatar $avatar) public function forceDeleted(Avatar $avatar)

View file

@ -102,6 +102,7 @@ class ConfigCacheService
'pixelfed.optimize_image', 'pixelfed.optimize_image',
'pixelfed.optimize_video', 'pixelfed.optimize_video',
'pixelfed.max_collection_length', 'pixelfed.max_collection_length',
'media.delete_local_after_cloud',
// 'system.user_mode' // 'system.user_mode'
]; ];

View file

@ -2,32 +2,26 @@
namespace App\Services; namespace App\Services;
use App\Jobs\AvatarPipeline\AvatarStorageCleanup;
use App\Jobs\MediaPipeline\MediaDeletePipeline;
use App\Media;
use App\Util\ActivityPub\Helpers; use App\Util\ActivityPub\Helpers;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Http\File; use Illuminate\Http\File;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Media;
use App\Profile;
use App\User;
use GuzzleHttp\Client;
use App\Services\AccountService;
use App\Http\Controllers\AvatarController;
use GuzzleHttp\Exception\RequestException;
use App\Jobs\MediaPipeline\MediaDeletePipeline;
use Illuminate\Support\Arr;
use App\Jobs\AvatarPipeline\AvatarStorageCleanup;
class MediaStorageService {
class MediaStorageService
{
public static function store(Media $media) public static function store(Media $media)
{ {
if(config_cache('pixelfed.cloud_storage') == true) { if ((bool) config_cache('pixelfed.cloud_storage') == true) {
(new self())->cloudStore($media); (new self())->cloudStore($media);
} }
return;
} }
public static function move(Media $media) public static function move(Media $media)
@ -36,10 +30,10 @@ class MediaStorageService {
return; return;
} }
if(config_cache('pixelfed.cloud_storage') == true) { if ((bool) config_cache('pixelfed.cloud_storage') == true) {
return (new self())->cloudMove($media); return (new self())->cloudMove($media);
} }
return;
} }
public static function avatar($avatar, $local = false, $skipRecentCheck = false) public static function avatar($avatar, $local = false, $skipRecentCheck = false)
@ -73,7 +67,7 @@ class MediaStorageService {
return [ return [
'length' => $len, 'length' => $len,
'mime' => $mime 'mime' => $mime,
]; ];
} }
@ -132,7 +126,7 @@ class MediaStorageService {
$mimes = [ $mimes = [
'image/jpeg', 'image/jpeg',
'image/png', 'image/png',
'video/mp4' 'video/mp4',
]; ];
$mime = $head['mime']; $mime = $head['mime'];
@ -258,6 +252,7 @@ class MediaStorageService {
$avatar->last_fetched_at = now(); $avatar->last_fetched_at = now();
$avatar->save(); $avatar->save();
unlink($tmpName); unlink($tmpName);
return; return;
} }

View file

@ -2,49 +2,34 @@
namespace App\Util\ActivityPub; namespace App\Util\ActivityPub;
use DB, Cache, Purify, Storage, Request, Validator; use App\Instance;
use App\{
Activity,
Follower,
Instance,
Like,
Media,
Notification,
Profile,
Status
};
use Zttp\Zttp;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Http\File;
use Illuminate\Validation\Rule;
use App\Jobs\AvatarPipeline\CreateAvatar;
use App\Jobs\RemoteFollowPipeline\RemoteFollowImportRecent;
use App\Jobs\ImageOptimizePipeline\{ImageOptimize,ImageThumbnail};
use App\Jobs\StatusPipeline\NewStatusPipeline;
use App\Jobs\StatusPipeline\StatusReplyPipeline;
use App\Jobs\StatusPipeline\StatusTagsPipeline;
use App\Util\ActivityPub\HttpSignature;
use Illuminate\Support\Str;
use App\Services\ActivityPubFetchService;
use App\Services\ActivityPubDeliveryService;
use App\Services\CustomEmojiService;
use App\Services\InstanceService;
use App\Services\MediaPathService;
use App\Services\MediaStorageService;
use App\Services\NetworkTimelineService;
use App\Jobs\MediaPipeline\MediaStoragePipeline;
use App\Jobs\AvatarPipeline\RemoteAvatarFetch; use App\Jobs\AvatarPipeline\RemoteAvatarFetch;
use App\Jobs\HomeFeedPipeline\FeedInsertRemotePipeline; use App\Jobs\HomeFeedPipeline\FeedInsertRemotePipeline;
use App\Util\Media\License; use App\Jobs\MediaPipeline\MediaStoragePipeline;
use App\Jobs\StatusPipeline\StatusReplyPipeline;
use App\Jobs\StatusPipeline\StatusTagsPipeline;
use App\Media;
use App\Models\Poll; use App\Models\Poll;
use Illuminate\Contracts\Cache\LockTimeoutException; use App\Profile;
use App\Services\DomainService;
use App\Services\UserFilterService;
use App\Services\Account\AccountStatService; use App\Services\Account\AccountStatService;
use App\Services\ActivityPubDeliveryService;
use App\Services\ActivityPubFetchService;
use App\Services\DomainService;
use App\Services\InstanceService;
use App\Services\MediaPathService;
use App\Services\NetworkTimelineService;
use App\Services\UserFilterService;
use App\Status;
use App\Util\Media\License;
use Cache;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Purify;
use Validator;
class Helpers { class Helpers
{
public static function validateObject($data) public static function validateObject($data)
{ {
$verbs = ['Create', 'Announce', 'Like', 'Follow', 'Delete', 'Accept', 'Reject', 'Undo', 'Tombstone']; $verbs = ['Create', 'Announce', 'Like', 'Follow', 'Delete', 'Accept', 'Reject', 'Undo', 'Tombstone'];
@ -53,14 +38,14 @@ class Helpers {
'type' => [ 'type' => [
'required', 'required',
'string', 'string',
Rule::in($verbs) Rule::in($verbs),
], ],
'id' => 'required|string', 'id' => 'required|string',
'actor' => 'required|string|url', 'actor' => 'required|string|url',
'object' => 'required', 'object' => 'required',
'object.type' => 'required_if:type,Create', 'object.type' => 'required_if:type,Create',
'object.attributedTo' => 'required_if:type,Create|url', 'object.attributedTo' => 'required_if:type,Create|url',
'published' => 'required_if:type,Create|date' 'published' => 'required_if:type,Create|date',
])->passes(); ])->passes();
return $valid; return $valid;
@ -100,13 +85,13 @@ class Helpers {
'*.type' => [ '*.type' => [
'required', 'required',
'string', 'string',
Rule::in($mediaTypes) Rule::in($mediaTypes),
], ],
'*.url' => 'required|url', '*.url' => 'required|url',
'*.mediaType' => [ '*.mediaType' => [
'required', 'required',
'string', 'string',
Rule::in($mimeTypes) Rule::in($mimeTypes),
], ],
'*.name' => 'sometimes|nullable|string', '*.name' => 'sometimes|nullable|string',
'*.blurhash' => 'sometimes|nullable|string|min:6|max:164', '*.blurhash' => 'sometimes|nullable|string|min:6|max:164',
@ -132,6 +117,7 @@ class Helpers {
foreach ($data['to'] as $to) { foreach ($data['to'] as $to) {
if ($to == 'https://www.w3.org/ns/activitystreams#Public') { if ($to == 'https://www.w3.org/ns/activitystreams#Public') {
$scope = 'public'; $scope = 'public';
continue; continue;
} }
$url = $localOnly ? self::validateLocalUrl($to) : self::validateUrl($to); $url = $localOnly ? self::validateLocalUrl($to) : self::validateUrl($to);
@ -145,6 +131,7 @@ class Helpers {
foreach ($data['cc'] as $cc) { foreach ($data['cc'] as $cc) {
if ($cc == 'https://www.w3.org/ns/activitystreams#Public') { if ($cc == 'https://www.w3.org/ns/activitystreams#Public') {
$scope = 'unlisted'; $scope = 'unlisted';
continue; continue;
} }
$url = $localOnly ? self::validateLocalUrl($cc) : self::validateUrl($cc); $url = $localOnly ? self::validateLocalUrl($cc) : self::validateUrl($cc);
@ -154,6 +141,7 @@ class Helpers {
} }
} }
$audience['scope'] = $scope; $audience['scope'] = $scope;
return $audience; return $audience;
} }
@ -161,6 +149,7 @@ class Helpers {
{ {
$audience = self::normalizeAudience($data); $audience = self::normalizeAudience($data);
$url = $profile->permalink(); $url = $profile->permalink();
return in_array($url, $audience['to']) || in_array($url, $audience['cc']); return in_array($url, $audience['to']) || in_array($url, $audience['cc']);
} }
@ -175,7 +164,7 @@ class Helpers {
$valid = Cache::remember($key, 900, function () use ($url) { $valid = Cache::remember($key, 900, function () use ($url) {
$localhosts = [ $localhosts = [
'127.0.0.1', 'localhost', '::1' '127.0.0.1', 'localhost', '::1',
]; ];
if (strtolower(mb_substr($url, 0, 8)) !== 'https://') { if (strtolower(mb_substr($url, 0, 8)) !== 'https://') {
@ -228,8 +217,10 @@ class Helpers {
$domain = config('pixelfed.domain.app'); $domain = config('pixelfed.domain.app');
$host = parse_url($url, PHP_URL_HOST); $host = parse_url($url, PHP_URL_HOST);
$url = strtolower($domain) === strtolower($host) ? $url : false; $url = strtolower($domain) === strtolower($host) ? $url : false;
return $url; return $url;
} }
return false; return false;
} }
@ -237,6 +228,7 @@ class Helpers {
{ {
$version = config('pixelfed.version'); $version = config('pixelfed.version');
$url = config('app.url'); $url = config('app.url');
return [ return [
'Accept' => 'application/activity+json', 'Accept' => 'application/activity+json',
'User-Agent' => "(Pixelfed/{$version}; +{$url})", 'User-Agent' => "(Pixelfed/{$version}; +{$url})",
@ -297,6 +289,7 @@ class Helpers {
if ($local) { if ($local) {
$id = (int) last(explode('/', $url)); $id = (int) last(explode('/', $url));
return Status::whereNotIn('scope', ['draft', 'archived'])->findOrFail($id); return Status::whereNotIn('scope', ['draft', 'archived'])->findOrFail($id);
} }
@ -346,7 +339,7 @@ class Helpers {
if (is_array($res['to']) && in_array('https://www.w3.org/ns/activitystreams#Public', $res['to'])) { if (is_array($res['to']) && in_array('https://www.w3.org/ns/activitystreams#Public', $res['to'])) {
$scope = 'public'; $scope = 'public';
} }
if(is_string($res['to']) && 'https://www.w3.org/ns/activitystreams#Public' == $res['to']) { if (is_string($res['to']) && $res['to'] == 'https://www.w3.org/ns/activitystreams#Public') {
$scope = 'public'; $scope = 'public';
} }
} }
@ -355,7 +348,7 @@ class Helpers {
if (is_array($res['cc']) && in_array('https://www.w3.org/ns/activitystreams#Public', $res['cc'])) { if (is_array($res['cc']) && in_array('https://www.w3.org/ns/activitystreams#Public', $res['cc'])) {
$scope = 'unlisted'; $scope = 'unlisted';
} }
if(is_string($res['cc']) && 'https://www.w3.org/ns/activitystreams#Public' == $res['cc']) { if (is_string($res['cc']) && $res['cc'] == 'https://www.w3.org/ns/activitystreams#Public') {
$scope = 'unlisted'; $scope = 'unlisted';
} }
} }
@ -417,8 +410,7 @@ class Helpers {
if (! self::validateUrl($attributedTo) || if (! self::validateUrl($attributedTo) ||
$idDomain !== $actorDomain || $idDomain !== $actorDomain ||
$actorDomain !== $urlDomain $actorDomain !== $urlDomain
) ) {
{
return; return;
} }
} }
@ -466,6 +458,7 @@ class Helpers {
$scope, $scope,
$id $id
); );
return $status; return $status;
} else { } else {
$status = self::storeStatus($url, $profile, $res); $status = self::storeStatus($url, $profile, $res);
@ -512,7 +505,7 @@ class Helpers {
$status = Status::updateOrCreate( $status = Status::updateOrCreate(
[ [
'uri' => $url 'uri' => $url,
], [ ], [
'profile_id' => $pid, 'profile_id' => $pid,
'url' => $url, 'url' => $url,
@ -527,7 +520,7 @@ class Helpers {
'visibility' => $scope, 'visibility' => $scope,
'cw_summary' => ($cw == true && isset($activity['summary']) ? 'cw_summary' => ($cw == true && isset($activity['summary']) ?
Purify::clean(strip_tags($activity['summary'])) : null), Purify::clean(strip_tags($activity['summary'])) : null),
'comments_disabled' => $commentsDisabled 'comments_disabled' => $commentsDisabled,
] ]
); );
@ -620,7 +613,7 @@ class Helpers {
if (is_array($activity['to']) && in_array('https://www.w3.org/ns/activitystreams#Public', $activity['to'])) { if (is_array($activity['to']) && in_array('https://www.w3.org/ns/activitystreams#Public', $activity['to'])) {
$scope = 'public'; $scope = 'public';
} }
if(is_string($activity['to']) && 'https://www.w3.org/ns/activitystreams#Public' == $activity['to']) { if (is_string($activity['to']) && $activity['to'] == 'https://www.w3.org/ns/activitystreams#Public') {
$scope = 'public'; $scope = 'public';
} }
} }
@ -629,7 +622,7 @@ class Helpers {
if (is_array($activity['cc']) && in_array('https://www.w3.org/ns/activitystreams#Public', $activity['cc'])) { if (is_array($activity['cc']) && in_array('https://www.w3.org/ns/activitystreams#Public', $activity['cc'])) {
$scope = 'unlisted'; $scope = 'unlisted';
} }
if(is_string($activity['cc']) && 'https://www.w3.org/ns/activitystreams#Public' == $activity['cc']) { if (is_string($activity['cc']) && $activity['cc'] == 'https://www.w3.org/ns/activitystreams#Public') {
$scope = 'unlisted'; $scope = 'unlisted';
} }
} }
@ -700,6 +693,7 @@ class Helpers {
if (self::verifyAttachments($data) == false) { if (self::verifyAttachments($data) == false) {
// \Log::info('importNoteAttachment::failedVerification.', [$data['id']]); // \Log::info('importNoteAttachment::failedVerification.', [$data['id']]);
$status->viewType(); $status->viewType();
return; return;
} }
$attachments = isset($data['object']) ? $data['object']['attachment'] : $data['attachment']; $attachments = isset($data['object']) ? $data['object']['attachment'] : $data['attachment'];
@ -748,13 +742,13 @@ class Helpers {
$media->version = 3; $media->version = 3;
$media->save(); $media->save();
if(config_cache('pixelfed.cloud_storage') == true) { if ((bool) config_cache('pixelfed.cloud_storage') == true) {
MediaStoragePipeline::dispatch($media); MediaStoragePipeline::dispatch($media);
} }
} }
$status->viewType(); $status->viewType();
return;
} }
public static function profileFirstOrNew($url) public static function profileFirstOrNew($url)
@ -769,6 +763,7 @@ class Helpers {
if ($local == true) { if ($local == true) {
$id = last(explode('/', $url)); $id = last(explode('/', $url));
return Profile::whereNull('status') return Profile::whereNull('status')
->whereNull('domain') ->whereNull('domain')
->whereUsername($id) ->whereUsername($id)
@ -779,6 +774,7 @@ class Helpers {
if ($profile->last_fetched_at && $profile->last_fetched_at->lt(now()->subHours(24))) { if ($profile->last_fetched_at && $profile->last_fetched_at->lt(now()->subHours(24))) {
return self::profileUpdateOrCreate($url); return self::profileUpdateOrCreate($url);
} }
return $profile; return $profile;
} }
@ -821,7 +817,7 @@ class Helpers {
} }
$instance = Instance::updateOrCreate([ $instance = Instance::updateOrCreate([
'domain' => $domain 'domain' => $domain,
]); ]);
if ($instance->wasRecentlyCreated == true) { if ($instance->wasRecentlyCreated == true) {
\App\Jobs\InstancePipeline\FetchNodeinfoPipeline::dispatch($instance)->onQueue('low'); \App\Jobs\InstancePipeline\FetchNodeinfoPipeline::dispatch($instance)->onQueue('low');
@ -853,6 +849,7 @@ class Helpers {
} }
$profile->last_fetched_at = now(); $profile->last_fetched_at = now();
$profile->save(); $profile->save();
return $profile; return $profile;
} }

View file

@ -740,7 +740,7 @@
<tr> <tr>
<td><span class="badge badge-primary">PIXELFED</span></td> <td><span class="badge badge-primary">PIXELFED</span></td>
<td><strong>PF_ENABLE_CLOUD</strong></td> <td><strong>PF_ENABLE_CLOUD</strong></td>
<td><span>{{config_cache('pixelfed.cloud_storage') ? '✅ true' : '❌ false' }}</span></td> <td><span>{{(bool) config_cache('pixelfed.cloud_storage') ? '✅ true' : '❌ false' }}</span></td>
</tr> </tr>
<tr> <tr>
<td><span class="badge badge-primary">PIXELFED</span></td> <td><span class="badge badge-primary">PIXELFED</span></td>