mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-10 00:34:50 +00:00
commit
0b162dc15e
113 changed files with 4975 additions and 2672 deletions
|
@ -21,7 +21,12 @@ jobs:
|
|||
steps:
|
||||
- checkout
|
||||
|
||||
- run: sudo apt update && sudo apt install zlib1g-dev libsqlite3-dev
|
||||
- run:
|
||||
name: "Create Environment file and generate app key"
|
||||
command: |
|
||||
mv .env.testing .env
|
||||
|
||||
- run: sudo apt install zlib1g-dev libsqlite3-dev
|
||||
|
||||
# Download and cache dependencies
|
||||
|
||||
|
@ -36,18 +41,17 @@ jobs:
|
|||
- run: composer install -n --prefer-dist
|
||||
|
||||
- save_cache:
|
||||
key: composer-v2-{{ checksum "composer.lock" }}
|
||||
key: v2-dependencies-{{ checksum "composer.json" }}
|
||||
paths:
|
||||
- vendor
|
||||
|
||||
- run: cp .env.testing .env
|
||||
- run: php artisan config:cache
|
||||
- run: php artisan route:clear
|
||||
- run: php artisan storage:link
|
||||
- run: php artisan key:generate
|
||||
|
||||
# run tests with phpunit or codecept
|
||||
- run: ./vendor/bin/phpunit
|
||||
- run: php artisan test
|
||||
- store_test_results:
|
||||
path: tests/_output
|
||||
- store_artifacts:
|
||||
|
|
|
@ -82,7 +82,7 @@ class AvatarStorage extends Command
|
|||
|
||||
$this->line(' ');
|
||||
|
||||
if(config_cache('pixelfed.cloud_storage')) {
|
||||
if((bool) config_cache('pixelfed.cloud_storage')) {
|
||||
$this->info('✅ - Cloud storage configured');
|
||||
$this->line(' ');
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class AvatarStorage extends Command
|
|||
$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'));
|
||||
$exists = $disk->exists('cache/avatars/default.jpg');
|
||||
$state = $exists ? '✅' : '❌';
|
||||
|
@ -100,7 +100,7 @@ class AvatarStorage extends Command
|
|||
$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',
|
||||
'Upload default avatar to cloud',
|
||||
|
@ -164,7 +164,7 @@ class AvatarStorage extends Command
|
|||
|
||||
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');
|
||||
return;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ class AvatarStorage extends Command
|
|||
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.');
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class AvatarStorageDeepClean extends Command
|
|||
$this->line(' ');
|
||||
|
||||
$storage = [
|
||||
'cloud' => boolval(config_cache('pixelfed.cloud_storage')),
|
||||
'cloud' => (bool) config_cache('pixelfed.cloud_storage'),
|
||||
'local' => boolval(config_cache('federation.avatars.store_local'))
|
||||
];
|
||||
|
||||
|
|
|
@ -35,12 +35,16 @@ class CloudMediaMigrate extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$enabled = config('pixelfed.cloud_storage');
|
||||
$enabled = (bool) config_cache('pixelfed.cloud_storage');
|
||||
if(!$enabled) {
|
||||
$this->error('Cloud storage not enabled. Exiting...');
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$this->confirm('Are you sure you want to proceed?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$limit = $this->option('limit');
|
||||
$hugeMode = $this->option('huge');
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Media;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use App\Services\MediaService;
|
||||
use App\Services\StatusService;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class FetchMissingMediaMimeType extends Command
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ class FetchMissingMediaMimeType extends Command
|
|||
continue;
|
||||
}
|
||||
|
||||
if(!in_array($res->header('content-type'), explode(',',config('pixelfed.media_types')))) {
|
||||
if (! in_array($res->header('content-type'), explode(',', config_cache('pixelfed.media_types')))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class FixMediaDriver extends Command
|
|||
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...');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
|
|||
|
||||
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->error('Aborting...');
|
||||
exit;
|
||||
|
|
|
@ -45,7 +45,7 @@ class MediaS3GarbageCollector extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$enabled = in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']);
|
||||
$enabled = (bool) config_cache('pixelfed.cloud_storage');
|
||||
if(!$enabled) {
|
||||
$this->error('Cloud storage not enabled. Exiting...');
|
||||
return;
|
||||
|
|
|
@ -33,7 +33,7 @@ class Kernel extends ConsoleKernel
|
|||
$schedule->command('gc:passwordreset')->dailyAt('09:41')->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);
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class AccountController extends Controller
|
|||
|
||||
$pid = $request->user()->profile_id;
|
||||
$count = UserFilterService::muteCount($pid);
|
||||
$maxLimit = intval(config('instance.user_filters.max_user_mutes'));
|
||||
$maxLimit = (int) config_cache('instance.user_filters.max_user_mutes');
|
||||
abort_if($count >= $maxLimit, 422, self::FILTER_LIMIT_MUTE_TEXT . $maxLimit . ' accounts');
|
||||
if($count == 0) {
|
||||
$filterCount = UserFilter::whereUserId($pid)->count();
|
||||
|
@ -260,7 +260,7 @@ class AccountController extends Controller
|
|||
]);
|
||||
$pid = $request->user()->profile_id;
|
||||
$count = UserFilterService::blockCount($pid);
|
||||
$maxLimit = intval(config('instance.user_filters.max_user_blocks'));
|
||||
$maxLimit = (int) config_cache('instance.user_filters.max_user_blocks');
|
||||
abort_if($count >= $maxLimit, 422, self::FILTER_LIMIT_BLOCK_TEXT . $maxLimit . ' accounts');
|
||||
if($count == 0) {
|
||||
$filterCount = UserFilter::whereUserId($pid)->whereFilterType('block')->count();
|
||||
|
|
|
@ -2,30 +2,20 @@
|
|||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use DB, Cache;
|
||||
use App\{
|
||||
DiscoverCategory,
|
||||
DiscoverCategoryHashtag,
|
||||
Hashtag,
|
||||
Media,
|
||||
Profile,
|
||||
Status,
|
||||
StatusHashtag,
|
||||
User
|
||||
};
|
||||
use App\Http\Controllers\PixelfedDirectoryController;
|
||||
use App\Models\ConfigCache;
|
||||
use App\Services\AccountService;
|
||||
use App\Services\ConfigCacheService;
|
||||
use App\Services\StatusService;
|
||||
use Carbon\Carbon;
|
||||
use App\Status;
|
||||
use App\User;
|
||||
use Cache;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use League\ISO3166\ISO3166;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use App\Http\Controllers\PixelfedDirectoryController;
|
||||
use Illuminate\Support\Str;
|
||||
use League\ISO3166\ISO3166;
|
||||
|
||||
trait AdminDirectoryController
|
||||
{
|
||||
|
@ -46,7 +36,7 @@ trait AdminDirectoryController
|
|||
'uid' => (string) $user->id,
|
||||
'pid' => (string) $user->profile_id,
|
||||
'username' => $user->username,
|
||||
'created_at' => $user->created_at
|
||||
'created_at' => $user->created_at,
|
||||
];
|
||||
});
|
||||
$config = ConfigCache::whereK('pixelfed.directory')->first();
|
||||
|
@ -84,14 +74,14 @@ trait AdminDirectoryController
|
|||
$res['feature_config'] = [
|
||||
'media_types' => Str::of(config_cache('pixelfed.media_types'))->explode(','),
|
||||
'image_quality' => config_cache('pixelfed.image_quality'),
|
||||
'optimize_image' => config_cache('pixelfed.optimize_image'),
|
||||
'optimize_image' => (bool) config_cache('pixelfed.optimize_image'),
|
||||
'max_photo_size' => config_cache('pixelfed.max_photo_size'),
|
||||
'max_caption_length' => config_cache('pixelfed.max_caption_length'),
|
||||
'max_altext_length' => config_cache('pixelfed.max_altext_length'),
|
||||
'enforce_account_limit' => config_cache('pixelfed.enforce_account_limit'),
|
||||
'enforce_account_limit' => (bool) config_cache('pixelfed.enforce_account_limit'),
|
||||
'max_account_size' => config_cache('pixelfed.max_account_size'),
|
||||
'max_album_length' => config_cache('pixelfed.max_album_length'),
|
||||
'account_deletion' => config_cache('pixelfed.account_deletion'),
|
||||
'account_deletion' => (bool) config_cache('pixelfed.account_deletion'),
|
||||
];
|
||||
|
||||
if (config_cache('pixelfed.directory.testimonials')) {
|
||||
|
@ -99,7 +89,7 @@ trait AdminDirectoryController
|
|||
->map(function ($t) {
|
||||
return [
|
||||
'profile' => AccountService::get($t['profile_id']),
|
||||
'body' => $t['body']
|
||||
'body' => $t['body'],
|
||||
];
|
||||
});
|
||||
$res['testimonials'] = $testimonials;
|
||||
|
@ -120,7 +110,7 @@ trait AdminDirectoryController
|
|||
'max_account_size' => 'required_if:enforce_account_limit,true|integer|min:1000000',
|
||||
'max_album_length' => 'required|integer|min:4|max:20',
|
||||
'account_deletion' => 'required|accepted',
|
||||
'max_caption_length' => 'required|integer|min:500|max:10000'
|
||||
'max_caption_length' => 'required|integer|min:500|max:10000',
|
||||
]);
|
||||
|
||||
$res['requirements_validator'] = $validator->errors();
|
||||
|
@ -160,10 +150,11 @@ trait AdminDirectoryController
|
|||
|
||||
$submissionState = Http::withoutVerifying()
|
||||
->post('https://pixelfed.org/api/v1/directory/check-submission', [
|
||||
'domain' => config('pixelfed.domain.app')
|
||||
'domain' => config('pixelfed.domain.app'),
|
||||
]);
|
||||
|
||||
$res['submission_state'] = $submissionState->json();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@ -194,11 +185,11 @@ trait AdminDirectoryController
|
|||
'favourite_posts' => 'array|max:12',
|
||||
'favourite_posts.*' => 'distinct',
|
||||
'privacy_pledge' => 'sometimes',
|
||||
'banner_image' => 'sometimes|mimes:jpg,png|dimensions:width=1920,height:1080|max:5000'
|
||||
'banner_image' => 'sometimes|mimes:jpg,png|dimensions:width=1920,height:1080|max:5000',
|
||||
]);
|
||||
|
||||
$config = ConfigCache::firstOrNew([
|
||||
'k' => 'pixelfed.directory'
|
||||
'k' => 'pixelfed.directory',
|
||||
]);
|
||||
|
||||
$res = $config->v ? json_decode($config->v, true) : [];
|
||||
|
@ -221,8 +212,9 @@ trait AdminDirectoryController
|
|||
$protected = [
|
||||
'public/headers/.gitignore',
|
||||
'public/headers/default.jpg',
|
||||
'public/headers/missing.png'
|
||||
'public/headers/missing.png',
|
||||
];
|
||||
|
||||
return ! in_array($name, $protected);
|
||||
})
|
||||
->each(function ($name) {
|
||||
|
@ -243,6 +235,7 @@ trait AdminDirectoryController
|
|||
if (isset($updated['banner_image'])) {
|
||||
$updated['banner_image'] = url(Storage::url($updated['banner_image']));
|
||||
}
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
|
@ -253,7 +246,7 @@ trait AdminDirectoryController
|
|||
'open_registration' => (bool) config_cache('pixelfed.open_registration'),
|
||||
'curated_onboarding' => (bool) config_cache('instance.curated_registration.enabled'),
|
||||
'activitypub_enabled' => config_cache('federation.activitypub.enabled'),
|
||||
'oauth_enabled' => config_cache('pixelfed.oauth_enabled'),
|
||||
'oauth_enabled' => (bool) config_cache('pixelfed.oauth_enabled'),
|
||||
'media_types' => Str::of(config_cache('pixelfed.media_types'))->explode(','),
|
||||
'image_quality' => config_cache('pixelfed.image_quality'),
|
||||
'optimize_image' => config_cache('pixelfed.optimize_image'),
|
||||
|
@ -285,7 +278,7 @@ trait AdminDirectoryController
|
|||
'max_account_size' => 'required_if:enforce_account_limit,true|integer|min:1000000',
|
||||
'max_album_length' => 'required|integer|min:4|max:20',
|
||||
'account_deletion' => 'required|accepted',
|
||||
'max_caption_length' => 'required|integer|min:500|max:10000'
|
||||
'max_caption_length' => 'required|integer|min:500|max:10000',
|
||||
]);
|
||||
|
||||
if (! $validator->validate()) {
|
||||
|
@ -297,6 +290,7 @@ trait AdminDirectoryController
|
|||
|
||||
$data = (new PixelfedDirectoryController())->buildListing();
|
||||
$res = Http::withoutVerifying()->post('https://pixelfed.org/api/v1/directory/submission', $data);
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
|
@ -312,7 +306,7 @@ trait AdminDirectoryController
|
|||
$protected = [
|
||||
'public/headers/.gitignore',
|
||||
'public/headers/default.jpg',
|
||||
'public/headers/missing.png'
|
||||
'public/headers/missing.png',
|
||||
];
|
||||
if (! $path || in_array($path, $protected)) {
|
||||
return;
|
||||
|
@ -328,6 +322,7 @@ trait AdminDirectoryController
|
|||
$bannerImage->save();
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
ConfigCacheService::put('pixelfed.directory', $directory);
|
||||
|
||||
return $bannerImage->v;
|
||||
}
|
||||
|
||||
|
@ -357,7 +352,7 @@ trait AdminDirectoryController
|
|||
public function directoryGetAddPostByIdSearch(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'q' => 'required|integer'
|
||||
'q' => 'required|integer',
|
||||
]);
|
||||
|
||||
$id = $request->input('q');
|
||||
|
@ -385,6 +380,7 @@ trait AdminDirectoryController
|
|||
})
|
||||
->values();
|
||||
ConfigCacheService::put('pixelfed.directory.testimonials', $existing);
|
||||
|
||||
return $existing;
|
||||
}
|
||||
|
||||
|
@ -392,13 +388,13 @@ trait AdminDirectoryController
|
|||
{
|
||||
$this->validate($request, [
|
||||
'username' => 'required',
|
||||
'body' => 'required|string|min:5|max:500'
|
||||
'body' => 'required|string|min:5|max:500',
|
||||
]);
|
||||
|
||||
$user = User::whereUsername($request->input('username'))->whereNull('status')->firstOrFail();
|
||||
|
||||
$configCache = ConfigCache::firstOrCreate([
|
||||
'k' => 'pixelfed.directory.testimonials'
|
||||
'k' => 'pixelfed.directory.testimonials',
|
||||
]);
|
||||
|
||||
$testimonials = $configCache->v ? collect(json_decode($configCache->v, true)) : collect([]);
|
||||
|
@ -409,7 +405,7 @@ trait AdminDirectoryController
|
|||
$testimonials->push([
|
||||
'profile_id' => (string) $user->profile_id,
|
||||
'username' => $request->input('username'),
|
||||
'body' => $request->input('body')
|
||||
'body' => $request->input('body'),
|
||||
]);
|
||||
|
||||
$configCache->v = json_encode($testimonials->toArray());
|
||||
|
@ -417,8 +413,9 @@ trait AdminDirectoryController
|
|||
ConfigCacheService::put('pixelfed.directory.testimonials', $configCache->v);
|
||||
$res = [
|
||||
'profile' => AccountService::get($user->profile_id),
|
||||
'body' => $request->input('body')
|
||||
'body' => $request->input('body'),
|
||||
];
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@ -426,7 +423,7 @@ trait AdminDirectoryController
|
|||
{
|
||||
$this->validate($request, [
|
||||
'profile_id' => 'required',
|
||||
'body' => 'required|string|min:5|max:500'
|
||||
'body' => 'required|string|min:5|max:500',
|
||||
]);
|
||||
|
||||
$profile_id = $request->input('profile_id');
|
||||
|
@ -434,7 +431,7 @@ trait AdminDirectoryController
|
|||
$user = User::whereProfileId($profile_id)->firstOrFail();
|
||||
|
||||
$configCache = ConfigCache::firstOrCreate([
|
||||
'k' => 'pixelfed.directory.testimonials'
|
||||
'k' => 'pixelfed.directory.testimonials',
|
||||
]);
|
||||
|
||||
$testimonials = $configCache->v ? collect(json_decode($configCache->v, true)) : collect([]);
|
||||
|
@ -443,6 +440,7 @@ trait AdminDirectoryController
|
|||
if ($t['profile_id'] == $profile_id) {
|
||||
$t['body'] = $body;
|
||||
}
|
||||
|
||||
return $t;
|
||||
})
|
||||
->values();
|
||||
|
|
|
@ -7,7 +7,9 @@ use App\Models\InstanceActor;
|
|||
use App\Page;
|
||||
use App\Profile;
|
||||
use App\Services\AccountService;
|
||||
use App\Services\AdminSettingsService;
|
||||
use App\Services\ConfigCacheService;
|
||||
use App\Services\FilesystemService;
|
||||
use App\User;
|
||||
use App\Util\Site\Config;
|
||||
use Artisan;
|
||||
|
@ -71,6 +73,7 @@ trait AdminSettingsController
|
|||
'admin_account_id' => 'nullable',
|
||||
'regs' => 'required|in:open,filtered,closed',
|
||||
'account_migration' => 'nullable',
|
||||
'rule_delete' => 'sometimes',
|
||||
]);
|
||||
|
||||
$orb = false;
|
||||
|
@ -310,4 +313,573 @@ trait AdminSettingsController
|
|||
|
||||
return view('admin.settings.system', compact('sys'));
|
||||
}
|
||||
|
||||
public function settingsApiFetch(Request $request)
|
||||
{
|
||||
$cloud_storage = ConfigCacheService::get('pixelfed.cloud_storage');
|
||||
$cloud_disk = config('filesystems.cloud');
|
||||
$cloud_ready = ! empty(config('filesystems.disks.'.$cloud_disk.'.key')) && ! empty(config('filesystems.disks.'.$cloud_disk.'.secret'));
|
||||
$types = explode(',', ConfigCacheService::get('pixelfed.media_types'));
|
||||
$rules = ConfigCacheService::get('app.rules') ? json_decode(ConfigCacheService::get('app.rules'), true) : [];
|
||||
$jpeg = in_array('image/jpg', $types) || in_array('image/jpeg', $types);
|
||||
$png = in_array('image/png', $types);
|
||||
$gif = in_array('image/gif', $types);
|
||||
$mp4 = in_array('video/mp4', $types);
|
||||
$webp = in_array('image/webp', $types);
|
||||
|
||||
$availableAdmins = User::whereIsAdmin(true)->get();
|
||||
$currentAdmin = config_cache('instance.admin.pid') ? AccountService::get(config_cache('instance.admin.pid'), true) : null;
|
||||
$openReg = (bool) config_cache('pixelfed.open_registration');
|
||||
$curOnboarding = (bool) config_cache('instance.curated_registration.enabled');
|
||||
$regState = $openReg ? 'open' : ($curOnboarding ? 'filtered' : 'closed');
|
||||
$accountMigration = (bool) config_cache('federation.migration');
|
||||
$autoFollow = config_cache('account.autofollow_usernames');
|
||||
if (strlen($autoFollow) > 3) {
|
||||
$autoFollow = explode(',', $autoFollow);
|
||||
}
|
||||
|
||||
$res = AdminSettingsService::getAll();
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
public function settingsApiRulesAdd(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'rule' => 'required|string|min:5|max:1000',
|
||||
]);
|
||||
|
||||
$rules = ConfigCacheService::get('app.rules');
|
||||
$val = $request->input('rule');
|
||||
if (! $rules) {
|
||||
ConfigCacheService::put('app.rules', json_encode([$val]));
|
||||
} else {
|
||||
$json = json_decode($rules, true);
|
||||
$count = count($json);
|
||||
if ($count >= 30) {
|
||||
return response()->json(['message' => 'Max rules limit reached, you can set up to 30 rules at a time.'], 400);
|
||||
}
|
||||
$json[] = $val;
|
||||
ConfigCacheService::put('app.rules', json_encode(array_values($json)));
|
||||
}
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return [$val];
|
||||
}
|
||||
|
||||
public function settingsApiRulesDelete(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'rule' => 'required|string',
|
||||
]);
|
||||
|
||||
$rules = ConfigCacheService::get('app.rules');
|
||||
$val = $request->input('rule');
|
||||
|
||||
if (! $rules) {
|
||||
return [];
|
||||
} else {
|
||||
$json = json_decode($rules, true);
|
||||
$idx = array_search($val, $json);
|
||||
if ($idx !== false) {
|
||||
unset($json[$idx]);
|
||||
$json = array_values($json);
|
||||
}
|
||||
ConfigCacheService::put('app.rules', json_encode(array_values($json)));
|
||||
}
|
||||
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return response()->json($json);
|
||||
}
|
||||
|
||||
public function settingsApiRulesDeleteAll(Request $request)
|
||||
{
|
||||
$rules = ConfigCacheService::get('app.rules');
|
||||
|
||||
if (! $rules) {
|
||||
return [];
|
||||
} else {
|
||||
ConfigCacheService::put('app.rules', json_encode([]));
|
||||
}
|
||||
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return response()->json([]);
|
||||
}
|
||||
|
||||
public function settingsApiAutofollowDelete(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'username' => 'required|string',
|
||||
]);
|
||||
|
||||
$username = $request->input('username');
|
||||
$names = [];
|
||||
$existing = config_cache('account.autofollow_usernames');
|
||||
if ($existing) {
|
||||
$names = explode(',', $existing);
|
||||
}
|
||||
|
||||
if (in_array($username, $names)) {
|
||||
$key = array_search($username, $names);
|
||||
if ($key !== false) {
|
||||
unset($names[$key]);
|
||||
}
|
||||
}
|
||||
ConfigCacheService::put('account.autofollow_usernames', implode(',', $names));
|
||||
|
||||
return response()->json(['accounts' => array_values($names)]);
|
||||
}
|
||||
|
||||
public function settingsApiAutofollowAdd(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'username' => 'required|string',
|
||||
]);
|
||||
|
||||
$username = $request->input('username');
|
||||
$names = [];
|
||||
$existing = config_cache('account.autofollow_usernames');
|
||||
if ($existing) {
|
||||
$names = explode(',', $existing);
|
||||
}
|
||||
|
||||
if ($existing && count($names)) {
|
||||
if (count($names) >= 5) {
|
||||
return response()->json(['message' => 'You can only add up to 5 accounts to be autofollowed.'], 400);
|
||||
}
|
||||
if (in_array(strtolower($username), array_map('strtolower', $names))) {
|
||||
return response()->json(['message' => 'User already exists, please try again.'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
$p = User::whereUsername($username)->whereNull('status')->first();
|
||||
if (! $p || in_array($p->username, $names)) {
|
||||
abort(404);
|
||||
}
|
||||
array_push($names, $p->username);
|
||||
ConfigCacheService::put('account.autofollow_usernames', implode(',', $names));
|
||||
|
||||
return response()->json(['accounts' => array_values($names)]);
|
||||
}
|
||||
|
||||
public function settingsApiUpdateType(Request $request, $type)
|
||||
{
|
||||
abort_unless(in_array($type, [
|
||||
'posts',
|
||||
'platform',
|
||||
'home',
|
||||
'landing',
|
||||
'branding',
|
||||
'media',
|
||||
'users',
|
||||
'storage',
|
||||
]), 400);
|
||||
|
||||
switch ($type) {
|
||||
case 'home':
|
||||
return $this->settingsApiUpdateHomeType($request);
|
||||
break;
|
||||
|
||||
case 'landing':
|
||||
return $this->settingsApiUpdateLandingType($request);
|
||||
break;
|
||||
|
||||
case 'posts':
|
||||
return $this->settingsApiUpdatePostsType($request);
|
||||
break;
|
||||
|
||||
case 'platform':
|
||||
return $this->settingsApiUpdatePlatformType($request);
|
||||
break;
|
||||
|
||||
case 'branding':
|
||||
return $this->settingsApiUpdateBrandingType($request);
|
||||
break;
|
||||
|
||||
case 'media':
|
||||
return $this->settingsApiUpdateMediaType($request);
|
||||
break;
|
||||
|
||||
case 'users':
|
||||
return $this->settingsApiUpdateUsersType($request);
|
||||
break;
|
||||
|
||||
case 'storage':
|
||||
return $this->settingsApiUpdateStorageType($request);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(404);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function settingsApiUpdateHomeType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'registration_status' => 'required|in:open,filtered,closed',
|
||||
'cloud_storage' => 'required',
|
||||
'activitypub_enabled' => 'required',
|
||||
'account_migration' => 'required',
|
||||
'mobile_apis' => 'required',
|
||||
'stories' => 'required',
|
||||
'instagram_import' => 'required',
|
||||
'autospam_enabled' => 'required',
|
||||
]);
|
||||
|
||||
$regStatus = $request->input('registration_status');
|
||||
ConfigCacheService::put('pixelfed.open_registration', $regStatus === 'open');
|
||||
ConfigCacheService::put('instance.curated_registration.enabled', $regStatus === 'filtered');
|
||||
$cloudStorage = $request->boolean('cloud_storage');
|
||||
if ($cloudStorage !== (bool) config_cache('pixelfed.cloud_storage')) {
|
||||
if (! $cloudStorage) {
|
||||
ConfigCacheService::put('pixelfed.cloud_storage', false);
|
||||
} else {
|
||||
$cloud_disk = config('filesystems.cloud');
|
||||
$cloud_ready = ! empty(config('filesystems.disks.'.$cloud_disk.'.key')) && ! empty(config('filesystems.disks.'.$cloud_disk.'.secret'));
|
||||
if (! $cloud_ready) {
|
||||
return redirect()->back()->withErrors(['cloud_storage' => 'Must configure cloud storage before enabling!']);
|
||||
} else {
|
||||
ConfigCacheService::put('pixelfed.cloud_storage', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigCacheService::put('federation.activitypub.enabled', $request->boolean('activitypub_enabled'));
|
||||
ConfigCacheService::put('federation.migration', $request->boolean('account_migration'));
|
||||
ConfigCacheService::put('pixelfed.oauth_enabled', $request->boolean('mobile_apis'));
|
||||
ConfigCacheService::put('instance.stories.enabled', $request->boolean('stories'));
|
||||
ConfigCacheService::put('pixelfed.import.instagram.enabled', $request->boolean('instagram_import'));
|
||||
ConfigCacheService::put('pixelfed.bouncer.enabled', $request->boolean('autospam_enabled'));
|
||||
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Cache::forget('api:v1:instance-data:contact');
|
||||
Config::refresh();
|
||||
|
||||
return $request->all();
|
||||
}
|
||||
|
||||
public function settingsApiUpdateLandingType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'current_admin' => 'required',
|
||||
'show_directory' => 'required',
|
||||
'show_explore' => 'required',
|
||||
]);
|
||||
|
||||
ConfigCacheService::put('instance.admin.pid', $request->input('current_admin'));
|
||||
ConfigCacheService::put('instance.landing.show_directory', $request->boolean('show_directory'));
|
||||
ConfigCacheService::put('instance.landing.show_explore', $request->boolean('show_explore'));
|
||||
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Cache::forget('api:v1:instance-data:contact');
|
||||
Config::refresh();
|
||||
|
||||
return $request->all();
|
||||
}
|
||||
|
||||
public function settingsApiUpdateMediaType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'image_quality' => 'required|integer|min:1|max:100',
|
||||
'max_album_length' => 'required|integer|min:1|max:20',
|
||||
'max_photo_size' => 'required|integer|min:100|max:50000',
|
||||
'media_types' => 'required',
|
||||
'optimize_image' => 'required',
|
||||
'optimize_video' => 'required',
|
||||
]);
|
||||
|
||||
$mediaTypes = $request->input('media_types');
|
||||
$mediaArray = explode(',', $mediaTypes);
|
||||
foreach ($mediaArray as $mediaType) {
|
||||
if (! in_array($mediaType, ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'video/mp4'])) {
|
||||
return redirect()->back()->withErrors(['media_types' => 'Invalid media type']);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigCacheService::put('pixelfed.media_types', $request->input('media_types'));
|
||||
ConfigCacheService::put('pixelfed.image_quality', $request->input('image_quality'));
|
||||
ConfigCacheService::put('pixelfed.max_album_length', $request->input('max_album_length'));
|
||||
ConfigCacheService::put('pixelfed.max_photo_size', $request->input('max_photo_size'));
|
||||
ConfigCacheService::put('pixelfed.optimize_image', $request->boolean('optimize_image'));
|
||||
ConfigCacheService::put('pixelfed.optimize_video', $request->boolean('optimize_video'));
|
||||
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Cache::forget('api:v1:instance-data:contact');
|
||||
Config::refresh();
|
||||
|
||||
return $request->all();
|
||||
}
|
||||
|
||||
public function settingsApiUpdateBrandingType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required',
|
||||
'short_description' => 'required',
|
||||
'long_description' => 'required',
|
||||
]);
|
||||
|
||||
ConfigCacheService::put('app.name', $request->input('name'));
|
||||
ConfigCacheService::put('app.short_description', $request->input('short_description'));
|
||||
ConfigCacheService::put('app.description', $request->input('long_description'));
|
||||
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Cache::forget('api:v1:instance-data:contact');
|
||||
Config::refresh();
|
||||
|
||||
return $request->all();
|
||||
}
|
||||
|
||||
public function settingsApiUpdatePostsType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'max_caption_length' => 'required|integer|min:5|max:10000',
|
||||
'max_altext_length' => 'required|integer|min:5|max:40000',
|
||||
]);
|
||||
|
||||
ConfigCacheService::put('pixelfed.max_caption_length', $request->input('max_caption_length'));
|
||||
ConfigCacheService::put('pixelfed.max_altext_length', $request->input('max_altext_length'));
|
||||
$res = [
|
||||
'max_caption_length' => $request->input('max_caption_length'),
|
||||
'max_altext_length' => $request->input('max_altext_length'),
|
||||
];
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function settingsApiUpdatePlatformType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'allow_app_registration' => 'required',
|
||||
'app_registration_rate_limit_attempts' => 'required|integer|min:1',
|
||||
'app_registration_rate_limit_decay' => 'required|integer|min:1',
|
||||
'app_registration_confirm_rate_limit_attempts' => 'required|integer|min:1',
|
||||
'app_registration_confirm_rate_limit_decay' => 'required|integer|min:1',
|
||||
'allow_post_embeds' => 'required',
|
||||
'allow_profile_embeds' => 'required',
|
||||
'captcha_enabled' => 'required',
|
||||
'captcha_on_login' => 'required_if_accepted:captcha_enabled',
|
||||
'captcha_on_register' => 'required_if_accepted:captcha_enabled',
|
||||
'captcha_secret' => 'required_if_accepted:captcha_enabled',
|
||||
'captcha_sitekey' => 'required_if_accepted:captcha_enabled',
|
||||
'custom_emoji_enabled' => 'required',
|
||||
]);
|
||||
|
||||
ConfigCacheService::put('pixelfed.allow_app_registration', $request->boolean('allow_app_registration'));
|
||||
ConfigCacheService::put('pixelfed.app_registration_rate_limit_attempts', $request->input('app_registration_rate_limit_attempts'));
|
||||
ConfigCacheService::put('pixelfed.app_registration_rate_limit_decay', $request->input('app_registration_rate_limit_decay'));
|
||||
ConfigCacheService::put('pixelfed.app_registration_confirm_rate_limit_attempts', $request->input('app_registration_confirm_rate_limit_attempts'));
|
||||
ConfigCacheService::put('pixelfed.app_registration_confirm_rate_limit_decay', $request->input('app_registration_confirm_rate_limit_decay'));
|
||||
ConfigCacheService::put('instance.embed.post', $request->boolean('allow_post_embeds'));
|
||||
ConfigCacheService::put('instance.embed.profile', $request->boolean('allow_profile_embeds'));
|
||||
ConfigCacheService::put('federation.custom_emoji.enabled', $request->boolean('custom_emoji_enabled'));
|
||||
$captcha = $request->boolean('captcha_enabled');
|
||||
if ($captcha) {
|
||||
$secret = $request->input('captcha_secret');
|
||||
$sitekey = $request->input('captcha_sitekey');
|
||||
if (config_cache('captcha.secret') != $secret && strpos($secret, '*') === false) {
|
||||
ConfigCacheService::put('captcha.secret', $secret);
|
||||
}
|
||||
if (config_cache('captcha.sitekey') != $sitekey && strpos($sitekey, '*') === false) {
|
||||
ConfigCacheService::put('captcha.sitekey', $sitekey);
|
||||
}
|
||||
ConfigCacheService::put('captcha.active.login', $request->boolean('captcha_on_login'));
|
||||
ConfigCacheService::put('captcha.active.register', $request->boolean('captcha_on_register'));
|
||||
ConfigCacheService::put('captcha.triggers.login.enabled', $request->boolean('captcha_on_login'));
|
||||
ConfigCacheService::put('captcha.enabled', true);
|
||||
} else {
|
||||
ConfigCacheService::put('captcha.enabled', false);
|
||||
}
|
||||
$res = [
|
||||
'allow_app_registration' => $request->boolean('allow_app_registration'),
|
||||
'app_registration_rate_limit_attempts' => $request->input('app_registration_rate_limit_attempts'),
|
||||
'app_registration_rate_limit_decay' => $request->input('app_registration_rate_limit_decay'),
|
||||
'app_registration_confirm_rate_limit_attempts' => $request->input('app_registration_confirm_rate_limit_attempts'),
|
||||
'app_registration_confirm_rate_limit_decay' => $request->input('app_registration_confirm_rate_limit_decay'),
|
||||
'allow_post_embeds' => $request->boolean('allow_post_embeds'),
|
||||
'allow_profile_embeds' => $request->boolean('allow_profile_embeds'),
|
||||
'captcha_enabled' => $request->boolean('captcha_enabled'),
|
||||
'captcha_on_login' => $request->boolean('captcha_on_login'),
|
||||
'captcha_on_register' => $request->boolean('captcha_on_register'),
|
||||
'captcha_secret' => $request->input('captcha_secret'),
|
||||
'captcha_sitekey' => $request->input('captcha_sitekey'),
|
||||
'custom_emoji_enabled' => $request->boolean('custom_emoji_enabled'),
|
||||
];
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function settingsApiUpdateUsersType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'require_email_verification' => 'required',
|
||||
'enforce_account_limit' => 'required',
|
||||
'max_account_size' => 'required|integer|min:50000',
|
||||
'admin_autofollow' => 'required',
|
||||
'admin_autofollow_accounts' => 'sometimes',
|
||||
'max_user_blocks' => 'required|integer|min:0|max:5000',
|
||||
'max_user_mutes' => 'required|integer|min:0|max:5000',
|
||||
'max_domain_blocks' => 'required|integer|min:0|max:5000',
|
||||
]);
|
||||
|
||||
$adminAutofollow = $request->boolean('admin_autofollow');
|
||||
$adminAutofollowAccounts = $request->input('admin_autofollow_accounts');
|
||||
if ($adminAutofollow) {
|
||||
if ($request->filled('admin_autofollow_accounts')) {
|
||||
$names = [];
|
||||
$existing = config_cache('account.autofollow_usernames');
|
||||
if ($existing) {
|
||||
$names = explode(',', $existing);
|
||||
foreach (array_map('strtolower', $adminAutofollowAccounts) as $afc) {
|
||||
if (in_array(strtolower($afc), array_map('strtolower', $names))) {
|
||||
continue;
|
||||
}
|
||||
$names[] = $afc;
|
||||
}
|
||||
} else {
|
||||
$names = $adminAutofollowAccounts;
|
||||
}
|
||||
if (! $names || count($names) == 0) {
|
||||
return response()->json(['message' => 'You need to assign autofollow accounts before you can enable it.'], 400);
|
||||
}
|
||||
if (count($names) > 5) {
|
||||
return response()->json(['message' => 'You can only add up to 5 accounts to be autofollowed.'.json_encode($names)], 400);
|
||||
}
|
||||
$autofollows = User::whereIn('username', $names)->whereNull('status')->pluck('username');
|
||||
$adminAutofollowAccounts = $autofollows->implode(',');
|
||||
ConfigCacheService::put('account.autofollow_usernames', $adminAutofollowAccounts);
|
||||
} else {
|
||||
return response()->json(['message' => 'You need to assign autofollow accounts before you can enable it.'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigCacheService::put('pixelfed.enforce_email_verification', $request->boolean('require_email_verification'));
|
||||
ConfigCacheService::put('pixelfed.enforce_account_limit', $request->boolean('enforce_account_limit'));
|
||||
ConfigCacheService::put('pixelfed.max_account_size', $request->input('max_account_size'));
|
||||
ConfigCacheService::put('account.autofollow', $request->boolean('admin_autofollow'));
|
||||
ConfigCacheService::put('instance.user_filters.max_user_blocks', (int) $request->input('max_user_blocks'));
|
||||
ConfigCacheService::put('instance.user_filters.max_user_mutes', (int) $request->input('max_user_mutes'));
|
||||
ConfigCacheService::put('instance.user_filters.max_domain_blocks', (int) $request->input('max_domain_blocks'));
|
||||
$res = [
|
||||
'require_email_verification' => $request->boolean('require_email_verification'),
|
||||
'enforce_account_limit' => $request->boolean('enforce_account_limit'),
|
||||
'admin_autofollow' => $request->boolean('admin_autofollow'),
|
||||
'admin_autofollow_accounts' => $adminAutofollowAccounts,
|
||||
'max_user_blocks' => $request->input('max_user_blocks'),
|
||||
'max_user_mutes' => $request->input('max_user_mutes'),
|
||||
'max_domain_blocks' => $request->input('max_domain_blocks'),
|
||||
];
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function settingsApiUpdateStorageType($request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'primary_disk' => 'required|in:local,cloud',
|
||||
'update_disk' => 'sometimes',
|
||||
'disk_config' => 'required_if_accepted:update_disk',
|
||||
'disk_config.driver' => 'required|in:s3,spaces',
|
||||
'disk_config.key' => 'required',
|
||||
'disk_config.secret' => 'required',
|
||||
'disk_config.region' => 'required',
|
||||
'disk_config.bucket' => 'required',
|
||||
'disk_config.visibility' => 'required',
|
||||
'disk_config.endpoint' => 'required',
|
||||
'disk_config.url' => 'nullable',
|
||||
]);
|
||||
|
||||
ConfigCacheService::put('pixelfed.cloud_storage', $request->input('primary_disk') === 'cloud');
|
||||
$res = [
|
||||
'primary_disk' => $request->input('primary_disk'),
|
||||
];
|
||||
if ($request->has('update_disk')) {
|
||||
$res['disk_config'] = $request->input('disk_config');
|
||||
$changes = [];
|
||||
$dkey = $request->input('disk_config.driver') === 's3' ? 'filesystems.disks.s3.' : 'filesystems.disks.spaces.';
|
||||
$key = $request->input('disk_config.key');
|
||||
$ckey = null;
|
||||
$secret = $request->input('disk_config.secret');
|
||||
$csecret = null;
|
||||
$region = $request->input('disk_config.region');
|
||||
$bucket = $request->input('disk_config.bucket');
|
||||
$visibility = $request->input('disk_config.visibility');
|
||||
$url = $request->input('disk_config.url');
|
||||
$endpoint = $request->input('disk_config.endpoint');
|
||||
if (strpos($key, '*') === false && $key != config_cache($dkey.'key')) {
|
||||
array_push($changes, 'key');
|
||||
} else {
|
||||
$ckey = config_cache($dkey.'key');
|
||||
}
|
||||
if (strpos($secret, '*') === false && $secret != config_cache($dkey.'secret')) {
|
||||
array_push($changes, 'secret');
|
||||
} else {
|
||||
$csecret = config_cache($dkey.'secret');
|
||||
}
|
||||
if ($region != config_cache($dkey.'region')) {
|
||||
array_push($changes, 'region');
|
||||
}
|
||||
if ($bucket != config_cache($dkey.'bucket')) {
|
||||
array_push($changes, 'bucket');
|
||||
}
|
||||
if ($visibility != config_cache($dkey.'visibility')) {
|
||||
array_push($changes, 'visibility');
|
||||
}
|
||||
if ($url != config_cache($dkey.'url')) {
|
||||
array_push($changes, 'url');
|
||||
}
|
||||
if ($endpoint != config_cache($dkey.'endpoint')) {
|
||||
array_push($changes, 'endpoint');
|
||||
}
|
||||
|
||||
if ($changes && count($changes)) {
|
||||
$isValid = FilesystemService::getVerifyCredentials(
|
||||
$ckey ?? $key,
|
||||
$csecret ?? $secret,
|
||||
$region,
|
||||
$bucket,
|
||||
$endpoint,
|
||||
);
|
||||
if (! $isValid) {
|
||||
return response()->json(['error' => true, 's3_vce' => true, 'message' => "<div class='border border-danger text-danger p-3 font-weight-bold rounded-lg'>The S3/Spaces credentials you provided are invalid, or the bucket does not have the proper permissions.</div><br/>Please check all fields and try again.<br/><br/><strong>Any cloud storage configuration changes you made have NOT been saved due to invalid credentials.</strong>"], 400);
|
||||
}
|
||||
}
|
||||
$res['changes'] = json_encode($changes);
|
||||
}
|
||||
Cache::forget('api:v1:instance-data:rules');
|
||||
Cache::forget('api:v1:instance-data-response-v1');
|
||||
Cache::forget('api:v2:instance-data-response-v2');
|
||||
Config::refresh();
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -424,7 +424,7 @@ class AdminController extends Controller
|
|||
|
||||
public function customEmojiHome(Request $request)
|
||||
{
|
||||
if(!config('federation.custom_emoji.enabled')) {
|
||||
if(!(bool) config_cache('federation.custom_emoji.enabled')) {
|
||||
return view('admin.custom-emoji.not-enabled');
|
||||
}
|
||||
$this->validate($request, [
|
||||
|
@ -497,7 +497,7 @@ class AdminController extends Controller
|
|||
|
||||
public function customEmojiToggleActive(Request $request, $id)
|
||||
{
|
||||
abort_unless(config('federation.custom_emoji.enabled'), 404);
|
||||
abort_unless((bool) config_cache('federation.custom_emoji.enabled'), 404);
|
||||
$emoji = CustomEmoji::findOrFail($id);
|
||||
$emoji->disabled = !$emoji->disabled;
|
||||
$emoji->save();
|
||||
|
@ -508,13 +508,13 @@ class AdminController extends Controller
|
|||
|
||||
public function customEmojiAdd(Request $request)
|
||||
{
|
||||
abort_unless(config('federation.custom_emoji.enabled'), 404);
|
||||
abort_unless((bool) config_cache('federation.custom_emoji.enabled'), 404);
|
||||
return view('admin.custom-emoji.add');
|
||||
}
|
||||
|
||||
public function customEmojiStore(Request $request)
|
||||
{
|
||||
abort_unless(config('federation.custom_emoji.enabled'), 404);
|
||||
abort_unless((bool) config_cache('federation.custom_emoji.enabled'), 404);
|
||||
$this->validate($request, [
|
||||
'shortcode' => [
|
||||
'required',
|
||||
|
@ -545,7 +545,7 @@ class AdminController extends Controller
|
|||
|
||||
public function customEmojiDelete(Request $request, $id)
|
||||
{
|
||||
abort_unless(config('federation.custom_emoji.enabled'), 404);
|
||||
abort_unless((bool) config_cache('federation.custom_emoji.enabled'), 404);
|
||||
$emoji = CustomEmoji::findOrFail($id);
|
||||
Storage::delete("public/{$emoji->media_path}");
|
||||
Cache::forget('pf:custom_emoji');
|
||||
|
@ -555,7 +555,7 @@ class AdminController extends Controller
|
|||
|
||||
public function customEmojiShowDuplicates(Request $request, $id)
|
||||
{
|
||||
abort_unless(config('federation.custom_emoji.enabled'), 404);
|
||||
abort_unless((bool) config_cache('federation.custom_emoji.enabled'), 404);
|
||||
$emoji = CustomEmoji::orderBy('id')->whereDisabled(false)->whereShortcode($id)->firstOrFail();
|
||||
$emojis = CustomEmoji::whereShortcode($id)->where('id', '!=', $emoji->id)->cursorPaginate(10);
|
||||
return view('admin.custom-emoji.duplicates', compact('emoji', 'emojis'));
|
||||
|
|
|
@ -131,7 +131,7 @@ class ApiV1Controller extends Controller
|
|||
*/
|
||||
public function apps(Request $request)
|
||||
{
|
||||
abort_if(! config_cache('pixelfed.oauth_enabled'), 404);
|
||||
abort_if(! (bool) config_cache('pixelfed.oauth_enabled'), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'client_name' => 'required',
|
||||
|
@ -1103,7 +1103,7 @@ class ApiV1Controller extends Controller
|
|||
}
|
||||
|
||||
$count = UserFilterService::blockCount($pid);
|
||||
$maxLimit = intval(config('instance.user_filters.max_user_blocks'));
|
||||
$maxLimit = (int) config_cache('instance.user_filters.max_user_blocks');
|
||||
if ($count == 0) {
|
||||
$filterCount = UserFilter::whereUserId($pid)
|
||||
->whereFilterType('block')
|
||||
|
@ -1632,7 +1632,7 @@ class ApiV1Controller extends Controller
|
|||
|
||||
return [
|
||||
'uri' => config('pixelfed.domain.app'),
|
||||
'title' => config('app.name'),
|
||||
'title' => config_cache('app.name'),
|
||||
'short_description' => config_cache('app.short_description'),
|
||||
'description' => config_cache('app.description'),
|
||||
'email' => config('instance.email'),
|
||||
|
@ -1650,11 +1650,11 @@ class ApiV1Controller extends Controller
|
|||
'configuration' => [
|
||||
'media_attachments' => [
|
||||
'image_matrix_limit' => 16777216,
|
||||
'image_size_limit' => config('pixelfed.max_photo_size') * 1024,
|
||||
'supported_mime_types' => explode(',', config('pixelfed.media_types')),
|
||||
'image_size_limit' => config_cache('pixelfed.max_photo_size') * 1024,
|
||||
'supported_mime_types' => explode(',', config_cache('pixelfed.media_types')),
|
||||
'video_frame_rate_limit' => 120,
|
||||
'video_matrix_limit' => 2304000,
|
||||
'video_size_limit' => config('pixelfed.max_photo_size') * 1024,
|
||||
'video_size_limit' => config_cache('pixelfed.max_photo_size') * 1024,
|
||||
],
|
||||
'polls' => [
|
||||
'max_characters_per_option' => 50,
|
||||
|
@ -1665,7 +1665,7 @@ class ApiV1Controller extends Controller
|
|||
'statuses' => [
|
||||
'characters_reserved_per_url' => 23,
|
||||
'max_characters' => (int) config_cache('pixelfed.max_caption_length'),
|
||||
'max_media_attachments' => (int) config('pixelfed.max_album_length'),
|
||||
'max_media_attachments' => (int) config_cache('pixelfed.max_album_length'),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -2145,7 +2145,7 @@ class ApiV1Controller extends Controller
|
|||
}
|
||||
|
||||
$count = UserFilterService::muteCount($pid);
|
||||
$maxLimit = intval(config('instance.user_filters.max_user_mutes'));
|
||||
$maxLimit = (int) config_cache('instance.user_filters.max_user_mutes');
|
||||
if ($count == 0) {
|
||||
$filterCount = UserFilter::whereUserId($pid)
|
||||
->whereFilterType('mute')
|
||||
|
@ -3308,9 +3308,9 @@ class ApiV1Controller extends Controller
|
|||
abort_unless($request->user()->tokenCan('write'), 403);
|
||||
|
||||
$this->validate($request, [
|
||||
'status' => 'nullable|string|max:' . config_cache('pixelfed.max_caption_length'),
|
||||
'status' => 'nullable|string|max:'.(int) config_cache('pixelfed.max_caption_length'),
|
||||
'in_reply_to_id' => 'nullable',
|
||||
'media_ids' => 'sometimes|array|max:'.config_cache('pixelfed.max_album_length'),
|
||||
'media_ids' => 'sometimes|array|max:'.(int) config_cache('pixelfed.max_album_length'),
|
||||
'sensitive' => 'nullable',
|
||||
'visibility' => 'string|in:private,unlisted,public',
|
||||
'spoiler_text' => 'sometimes|max:140',
|
||||
|
@ -3436,7 +3436,7 @@ class ApiV1Controller extends Controller
|
|||
$mimes = [];
|
||||
|
||||
foreach ($ids as $k => $v) {
|
||||
if ($k + 1 > config_cache('pixelfed.max_album_length')) {
|
||||
if ($k + 1 > (int) config_cache('pixelfed.max_album_length')) {
|
||||
continue;
|
||||
}
|
||||
$m = Media::whereUserId($user->id)->whereNull('status_id')->findOrFail($v);
|
||||
|
|
|
@ -72,7 +72,7 @@ class DomainBlockController extends Controller
|
|||
abort_if(config_cache('pixelfed.domain.app') == $domain, 400, 'Cannot ban your own server');
|
||||
|
||||
$existingCount = UserDomainBlock::whereProfileId($pid)->count();
|
||||
$maxLimit = config('instance.user_filters.max_domain_blocks');
|
||||
$maxLimit = (int) config_cache('instance.user_filters.max_domain_blocks');
|
||||
$errorMsg = __('profile.block.domain.max', ['max' => $maxLimit]);
|
||||
|
||||
abort_if($existingCount >= $maxLimit, 400, $errorMsg);
|
||||
|
|
|
@ -62,7 +62,7 @@ class ForgotPasswordController extends Controller
|
|||
|
||||
usleep(random_int(100000, 3000000));
|
||||
|
||||
if(config('captcha.enabled')) {
|
||||
if((bool) config_cache('captcha.enabled')) {
|
||||
$rules = [
|
||||
'email' => 'required|email',
|
||||
'h-captcha-response' => 'required|captcha'
|
||||
|
|
|
@ -74,10 +74,10 @@ class LoginController extends Controller
|
|||
$messages = [];
|
||||
|
||||
if(
|
||||
config('captcha.enabled') ||
|
||||
config('captcha.active.login') ||
|
||||
(bool) config_cache('captcha.enabled') &&
|
||||
(bool) config_cache('captcha.active.login') ||
|
||||
(
|
||||
config('captcha.triggers.login.enabled') &&
|
||||
(bool) config_cache('captcha.triggers.login.enabled') &&
|
||||
request()->session()->has('login_attempts') &&
|
||||
request()->session()->get('login_attempts') >= config('captcha.triggers.login.attempts')
|
||||
)
|
||||
|
|
|
@ -137,7 +137,7 @@ class RegisterController extends Controller
|
|||
'password' => 'required|string|min:'.config('pixelfed.min_password_length').'|confirmed',
|
||||
];
|
||||
|
||||
if(config('captcha.enabled') || config('captcha.active.register')) {
|
||||
if((bool) config_cache('captcha.enabled') && (bool) config_cache('captcha.active.register')) {
|
||||
$rules['h-captcha-response'] = 'required|captcha';
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ class ResetPasswordController extends Controller
|
|||
{
|
||||
usleep(random_int(100000, 3000000));
|
||||
|
||||
if(config('captcha.enabled')) {
|
||||
if((bool) config_cache('captcha.enabled')) {
|
||||
return [
|
||||
'token' => 'required',
|
||||
'email' => 'required|email',
|
||||
|
|
|
@ -741,7 +741,7 @@ class ComposeController extends Controller
|
|||
case 'image/jpeg':
|
||||
case 'image/png':
|
||||
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;
|
||||
|
||||
default:
|
||||
|
|
|
@ -2,41 +2,25 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Jobs\InboxPipeline\{
|
||||
DeleteWorker,
|
||||
InboxWorker,
|
||||
InboxValidator
|
||||
};
|
||||
use App\Jobs\RemoteFollowPipeline\RemoteFollowPipeline;
|
||||
use App\{
|
||||
AccountLog,
|
||||
Like,
|
||||
Profile,
|
||||
Status,
|
||||
User
|
||||
};
|
||||
use App\Util\Lexer\Nickname;
|
||||
use App\Util\Webfinger\Webfinger;
|
||||
use Auth;
|
||||
use Cache;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal;
|
||||
use App\Util\Site\Nodeinfo;
|
||||
use App\Util\ActivityPub\{
|
||||
Helpers,
|
||||
HttpSignature,
|
||||
Outbox
|
||||
};
|
||||
use Zttp\Zttp;
|
||||
use App\Services\InstanceService;
|
||||
use App\Jobs\InboxPipeline\DeleteWorker;
|
||||
use App\Jobs\InboxPipeline\InboxValidator;
|
||||
use App\Jobs\InboxPipeline\InboxWorker;
|
||||
use App\Profile;
|
||||
use App\Services\AccountService;
|
||||
use App\Services\InstanceService;
|
||||
use App\Status;
|
||||
use App\Util\Lexer\Nickname;
|
||||
use App\Util\Site\Nodeinfo;
|
||||
use App\Util\Webfinger\Webfinger;
|
||||
use Cache;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FederationController extends Controller
|
||||
{
|
||||
public function nodeinfoWellKnown()
|
||||
{
|
||||
abort_if(! config('federation.nodeinfo.enabled'), 404);
|
||||
|
||||
return response()->json(Nodeinfo::wellKnown(), 200, [], JSON_UNESCAPED_SLASHES)
|
||||
->header('Access-Control-Allow-Origin', '*');
|
||||
}
|
||||
|
@ -44,6 +28,7 @@ class FederationController extends Controller
|
|||
public function nodeinfo()
|
||||
{
|
||||
abort_if(! config('federation.nodeinfo.enabled'), 404);
|
||||
|
||||
return response()->json(Nodeinfo::get(), 200, [], JSON_UNESCAPED_SLASHES)
|
||||
->header('Access-Control-Allow-Origin', '*');
|
||||
}
|
||||
|
@ -65,21 +50,22 @@ class FederationController extends Controller
|
|||
$res = [
|
||||
'subject' => 'acct:'.$domain.'@'.$domain,
|
||||
'aliases' => [
|
||||
'https://' . $domain . '/i/actor'
|
||||
'https://'.$domain.'/i/actor',
|
||||
],
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'http://webfinger.net/rel/profile-page',
|
||||
'type' => 'text/html',
|
||||
'href' => 'https://' . $domain . '/site/kb/instance-actor'
|
||||
'href' => 'https://'.$domain.'/site/kb/instance-actor',
|
||||
],
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => 'https://' . $domain . '/i/actor'
|
||||
]
|
||||
]
|
||||
'href' => 'https://'.$domain.'/i/actor',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return response()->json($res, 200, [], JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
$hash = hash('sha256', $resource);
|
||||
|
@ -118,7 +104,7 @@ class FederationController extends Controller
|
|||
|
||||
public function userOutbox(Request $request, $username)
|
||||
{
|
||||
abort_if(!config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
|
||||
|
||||
if (! $request->wantsJson()) {
|
||||
return redirect('/'.$username);
|
||||
|
@ -140,7 +126,7 @@ class FederationController extends Controller
|
|||
|
||||
public function userInbox(Request $request, $username)
|
||||
{
|
||||
abort_if(!config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! config('federation.activitypub.inbox'), 404);
|
||||
|
||||
$headers = $request->headers->all();
|
||||
|
@ -162,6 +148,7 @@ class FederationController extends Controller
|
|||
if ($obj['object']['type'] === 'Person') {
|
||||
if (Profile::whereRemoteUrl($obj['object']['id'])->exists()) {
|
||||
dispatch(new DeleteWorker($headers, $payload))->onQueue('inbox');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -169,27 +156,30 @@ class FederationController extends Controller
|
|||
if ($obj['object']['type'] === 'Tombstone') {
|
||||
if (Status::whereObjectUrl($obj['object']['id'])->exists()) {
|
||||
dispatch(new DeleteWorker($headers, $payload))->onQueue('delete');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($obj['object']['type'] === 'Story') {
|
||||
dispatch(new DeleteWorker($headers, $payload))->onQueue('story');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} elseif (isset($obj['type']) && in_array($obj['type'], ['Follow', 'Accept'])) {
|
||||
dispatch(new InboxValidator($username, $headers, $payload))->onQueue('follow');
|
||||
} else {
|
||||
dispatch(new InboxValidator($username, $headers, $payload))->onQueue('high');
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public function sharedInbox(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! config('federation.activitypub.sharedInbox'), 404);
|
||||
|
||||
$headers = $request->headers->all();
|
||||
|
@ -214,6 +204,7 @@ class FederationController extends Controller
|
|||
if ($obj['object']['type'] === 'Person') {
|
||||
if (Profile::whereRemoteUrl($obj['object']['id'])->exists()) {
|
||||
dispatch(new DeleteWorker($headers, $payload))->onQueue('inbox');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -221,27 +212,30 @@ class FederationController extends Controller
|
|||
if ($obj['object']['type'] === 'Tombstone') {
|
||||
if (Status::whereObjectUrl($obj['object']['id'])->exists()) {
|
||||
dispatch(new DeleteWorker($headers, $payload))->onQueue('delete');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($obj['object']['type'] === 'Story') {
|
||||
dispatch(new DeleteWorker($headers, $payload))->onQueue('story');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} elseif (isset($obj['type']) && in_array($obj['type'], ['Follow', 'Accept'])) {
|
||||
dispatch(new InboxWorker($headers, $payload))->onQueue('follow');
|
||||
} else {
|
||||
dispatch(new InboxWorker($headers, $payload))->onQueue('shared');
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public function userFollowing(Request $request, $username)
|
||||
{
|
||||
abort_if(!config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
|
||||
|
||||
$id = AccountService::usernameToId($username);
|
||||
abort_if(! $id, 404);
|
||||
|
@ -253,12 +247,13 @@ class FederationController extends Controller
|
|||
'type' => 'OrderedCollection',
|
||||
'totalItems' => $account['following_count'] ?? 0,
|
||||
];
|
||||
|
||||
return response()->json($obj)->header('Content-Type', 'application/activity+json');
|
||||
}
|
||||
|
||||
public function userFollowers(Request $request, $username)
|
||||
{
|
||||
abort_if(!config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
|
||||
$id = AccountService::usernameToId($username);
|
||||
abort_if(! $id, 404);
|
||||
$account = AccountService::get($id);
|
||||
|
@ -269,6 +264,7 @@ class FederationController extends Controller
|
|||
'type' => 'OrderedCollection',
|
||||
'totalItems' => $account['followers_count'] ?? 0,
|
||||
];
|
||||
|
||||
return response()->json($obj)->header('Content-Type', 'application/activity+json');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ trait Instagram
|
|||
{
|
||||
public function instagram()
|
||||
{
|
||||
if(config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
return view('settings.import.instagram.home');
|
||||
|
@ -25,6 +25,9 @@ trait Instagram
|
|||
|
||||
public function instagramStart(Request $request)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$completed = ImportJob::whereProfileId(Auth::user()->profile->id)
|
||||
->whereService('instagram')
|
||||
->whereNotNull('completed_at')
|
||||
|
@ -38,6 +41,9 @@ trait Instagram
|
|||
|
||||
protected function instagramRedirectOrNew()
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$profile = Auth::user()->profile;
|
||||
$exists = ImportJob::whereProfileId($profile->id)
|
||||
->whereService('instagram')
|
||||
|
@ -61,6 +67,9 @@ trait Instagram
|
|||
|
||||
public function instagramStepOne(Request $request, $uuid)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$profile = Auth::user()->profile;
|
||||
$job = ImportJob::whereProfileId($profile->id)
|
||||
->whereNull('completed_at')
|
||||
|
@ -72,6 +81,9 @@ trait Instagram
|
|||
|
||||
public function instagramStepOneStore(Request $request, $uuid)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$max = 'max:' . config('pixelfed.import.instagram.limits.size');
|
||||
$this->validate($request, [
|
||||
'media.*' => 'required|mimes:bin,jpeg,png,gif|'.$max,
|
||||
|
@ -114,6 +126,9 @@ trait Instagram
|
|||
|
||||
public function instagramStepTwo(Request $request, $uuid)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$profile = Auth::user()->profile;
|
||||
$job = ImportJob::whereProfileId($profile->id)
|
||||
->whereNull('completed_at')
|
||||
|
@ -125,6 +140,9 @@ trait Instagram
|
|||
|
||||
public function instagramStepTwoStore(Request $request, $uuid)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$this->validate($request, [
|
||||
'media' => 'required|file|max:1000'
|
||||
]);
|
||||
|
@ -150,6 +168,9 @@ trait Instagram
|
|||
|
||||
public function instagramStepThree(Request $request, $uuid)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$profile = Auth::user()->profile;
|
||||
$job = ImportJob::whereProfileId($profile->id)
|
||||
->whereService('instagram')
|
||||
|
@ -162,6 +183,9 @@ trait Instagram
|
|||
|
||||
public function instagramStepThreeStore(Request $request, $uuid)
|
||||
{
|
||||
if((bool) config_cache('pixelfed.import.instagram.enabled') != true) {
|
||||
abort(404, 'Feature not enabled');
|
||||
}
|
||||
$profile = Auth::user()->profile;
|
||||
|
||||
try {
|
||||
|
|
|
@ -179,7 +179,7 @@ class ImportPostController extends Controller
|
|||
'required',
|
||||
'file',
|
||||
$mimes,
|
||||
'max:' . config('pixelfed.max_photo_size')
|
||||
'max:' . config_cache('pixelfed.max_photo_size')
|
||||
]
|
||||
]);
|
||||
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Profile;
|
||||
use App\Services\AccountService;
|
||||
use App\Http\Resources\DirectoryProfile;
|
||||
use App\Profile;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LandingController extends Controller
|
||||
{
|
||||
|
@ -15,7 +14,7 @@ class LandingController extends Controller
|
|||
return redirect('/');
|
||||
}
|
||||
|
||||
abort_if(config_cache('instance.landing.show_directory') == false, 404);
|
||||
abort_if((bool) config_cache('instance.landing.show_directory') == false, 404);
|
||||
|
||||
return view('site.index');
|
||||
}
|
||||
|
@ -26,14 +25,14 @@ class LandingController extends Controller
|
|||
return redirect('/');
|
||||
}
|
||||
|
||||
abort_if(config_cache('instance.landing.show_explore') == false, 404);
|
||||
abort_if((bool) config_cache('instance.landing.show_explore') == false, 404);
|
||||
|
||||
return view('site.index');
|
||||
}
|
||||
|
||||
public function getDirectoryApi(Request $request)
|
||||
{
|
||||
abort_if(config_cache('instance.landing.show_directory') == false, 404);
|
||||
abort_if((bool) config_cache('instance.landing.show_directory') == false, 404);
|
||||
|
||||
return DirectoryProfile::collection(
|
||||
Profile::whereNull('domain')
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Media;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MediaController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
//return view('settings.drive.index');
|
||||
abort(404);
|
||||
}
|
||||
|
||||
public function composeUpdate(Request $request, $id)
|
||||
|
@ -19,7 +20,7 @@ class MediaController extends Controller
|
|||
|
||||
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;
|
||||
$media = Media::whereProfileId($pid)
|
||||
->whereMediaPath($path)
|
||||
|
|
|
@ -2,12 +2,15 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\ConfigCache;
|
||||
use Storage;
|
||||
use App\Services\AccountService;
|
||||
use App\Services\StatusService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Cache;
|
||||
use Storage;
|
||||
use App\Status;
|
||||
use App\User;
|
||||
|
||||
class PixelfedDirectoryController extends Controller
|
||||
{
|
||||
|
@ -26,6 +29,7 @@ class PixelfedDirectoryController extends Controller
|
|||
}
|
||||
|
||||
$res = $this->buildListing();
|
||||
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
|
@ -67,7 +71,7 @@ class PixelfedDirectoryController extends Controller
|
|||
'display_name' => $post['account']['display_name'],
|
||||
'username' => $post['account']['username'],
|
||||
'media' => $post['media_attachments'][0]['url'],
|
||||
'url' => $post['url']
|
||||
'url' => $post['url'],
|
||||
];
|
||||
})
|
||||
->values();
|
||||
|
@ -98,14 +102,14 @@ class PixelfedDirectoryController extends Controller
|
|||
$res['feature_config'] = [
|
||||
'media_types' => Str::of(config_cache('pixelfed.media_types'))->explode(','),
|
||||
'image_quality' => config_cache('pixelfed.image_quality'),
|
||||
'optimize_image' => config_cache('pixelfed.optimize_image'),
|
||||
'optimize_image' => (bool) config_cache('pixelfed.optimize_image'),
|
||||
'max_photo_size' => config_cache('pixelfed.max_photo_size'),
|
||||
'max_caption_length' => config_cache('pixelfed.max_caption_length'),
|
||||
'max_altext_length' => config_cache('pixelfed.max_altext_length'),
|
||||
'enforce_account_limit' => config_cache('pixelfed.enforce_account_limit'),
|
||||
'enforce_account_limit' => (bool) config_cache('pixelfed.enforce_account_limit'),
|
||||
'max_account_size' => config_cache('pixelfed.max_account_size'),
|
||||
'max_album_length' => config_cache('pixelfed.max_album_length'),
|
||||
'account_deletion' => config_cache('pixelfed.account_deletion'),
|
||||
'account_deletion' => (bool) config_cache('pixelfed.account_deletion'),
|
||||
];
|
||||
|
||||
$res['is_eligible'] = $this->validVal($res, 'admin') &&
|
||||
|
@ -119,25 +123,32 @@ class PixelfedDirectoryController extends Controller
|
|||
$res['testimonials'] = collect(json_decode(config_cache('pixelfed.directory.testimonials'), true))
|
||||
->map(function ($testimonial) {
|
||||
$profile = AccountService::get($testimonial['profile_id']);
|
||||
|
||||
return [
|
||||
'profile' => [
|
||||
'username' => $profile['username'],
|
||||
'display_name' => $profile['display_name'],
|
||||
'avatar' => $profile['avatar'],
|
||||
'created_at' => $profile['created_at']
|
||||
'created_at' => $profile['created_at'],
|
||||
],
|
||||
'body' => $testimonial['body']
|
||||
'body' => $testimonial['body'],
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
$res['features_enabled'] = [
|
||||
'stories' => (bool) config_cache('instance.stories.enabled')
|
||||
'stories' => (bool) config_cache('instance.stories.enabled'),
|
||||
];
|
||||
|
||||
$statusesCount = Cache::remember('api:nodeinfo:statuses', 21600, function() {
|
||||
return Status::whereLocal(true)->count();
|
||||
});
|
||||
$usersCount = Cache::remember('api:nodeinfo:users', 43200, function() {
|
||||
return User::count();
|
||||
});
|
||||
$res['stats'] = [
|
||||
'user_count' => \App\User::count(),
|
||||
'post_count' => \App\Status::whereNull('uri')->count(),
|
||||
'user_count' => (int) $usersCount,
|
||||
'post_count' => (int) $statusesCount,
|
||||
];
|
||||
|
||||
$res['primary_locale'] = config('app.locale');
|
||||
|
@ -164,5 +175,4 @@ class PixelfedDirectoryController extends Controller
|
|||
|
||||
return $res[$val];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -172,6 +172,8 @@ class ProfileController extends Controller
|
|||
|
||||
$user = $this->getCachedUser($username);
|
||||
|
||||
abort_if(!$user, 404);
|
||||
|
||||
return redirect($user->url());
|
||||
}
|
||||
|
||||
|
@ -371,7 +373,7 @@ class ProfileController extends Controller
|
|||
|
||||
public function stories(Request $request, $username)
|
||||
{
|
||||
abort_if(! config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$profile = Profile::whereNull('domain')->whereUsername($username)->firstOrFail();
|
||||
$pid = $profile->id;
|
||||
$authed = Auth::user()->profile_id;
|
||||
|
|
|
@ -2,22 +2,20 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\Account\RemoteAuthService;
|
||||
use App\Models\RemoteAuth;
|
||||
use App\Profile;
|
||||
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\Account\RemoteAuthService;
|
||||
use App\Services\EmailService;
|
||||
use App\Services\MediaStorageService;
|
||||
use App\User;
|
||||
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 Purify;
|
||||
|
||||
class RemoteAuthController extends Controller
|
||||
{
|
||||
|
@ -33,6 +31,7 @@ class RemoteAuthController extends Controller
|
|||
if ($request->user()) {
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
return view('auth.remote.start');
|
||||
}
|
||||
|
||||
|
@ -57,6 +56,7 @@ class RemoteAuthController extends Controller
|
|||
return [];
|
||||
}
|
||||
$res = explode(',', $res);
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,7 @@ class RemoteAuthController extends Controller
|
|||
return [];
|
||||
}
|
||||
$res = explode(',', $res);
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
|
@ -97,8 +98,9 @@ class RemoteAuthController extends Controller
|
|||
$res = [
|
||||
'domain' => $domain,
|
||||
'ready' => false,
|
||||
'action' => 'incompatible_domain'
|
||||
'action' => 'incompatible_domain',
|
||||
];
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
|
@ -108,8 +110,9 @@ class RemoteAuthController extends Controller
|
|||
$res = [
|
||||
'domain' => $domain,
|
||||
'ready' => false,
|
||||
'action' => 'blocked_domain'
|
||||
'action' => 'blocked_domain',
|
||||
];
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
|
@ -119,8 +122,9 @@ class RemoteAuthController extends Controller
|
|||
$res = [
|
||||
'domain' => $domain,
|
||||
'ready' => false,
|
||||
'action' => 'incompatible_domain'
|
||||
'action' => 'incompatible_domain',
|
||||
];
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
|
@ -130,8 +134,9 @@ class RemoteAuthController extends Controller
|
|||
$res = [
|
||||
'domain' => $domain,
|
||||
'ready' => false,
|
||||
'action' => 'incompatible_domain'
|
||||
'action' => 'incompatible_domain',
|
||||
];
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
}
|
||||
|
@ -142,8 +147,9 @@ class RemoteAuthController extends Controller
|
|||
$res = [
|
||||
'domain' => $domain,
|
||||
'ready' => false,
|
||||
'action' => 'incompatible_domain'
|
||||
'action' => 'incompatible_domain',
|
||||
];
|
||||
|
||||
return response()->json($res);
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +175,7 @@ class RemoteAuthController extends Controller
|
|||
$res = [
|
||||
'domain' => $domain,
|
||||
'ready' => true,
|
||||
'dsh' => $dsh
|
||||
'dsh' => $dsh,
|
||||
];
|
||||
|
||||
return response()->json($res);
|
||||
|
@ -218,10 +224,12 @@ class RemoteAuthController extends Controller
|
|||
|
||||
if (! $res || ! isset($res['access_token'])) {
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect('/login');
|
||||
}
|
||||
|
||||
$request->session()->put('oauth_remote_session_token', $res['access_token']);
|
||||
|
||||
return redirect('/auth/mastodon/getting-started');
|
||||
}
|
||||
|
||||
|
@ -240,6 +248,7 @@ class RemoteAuthController extends Controller
|
|||
if ($request->user()) {
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
return view('auth.remote.onboarding');
|
||||
}
|
||||
|
||||
|
@ -273,7 +282,7 @@ class RemoteAuthController extends Controller
|
|||
return response()->json([
|
||||
'code' => 200,
|
||||
'msg' => 'Success!',
|
||||
'action' => 'max_uses_reached'
|
||||
'action' => 'max_uses_reached',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -283,14 +292,14 @@ class RemoteAuthController extends Controller
|
|||
return response()->json([
|
||||
'code' => 200,
|
||||
'msg' => 'Success!',
|
||||
'action' => 'redirect_existing_user'
|
||||
'action' => 'redirect_existing_user',
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'code' => 200,
|
||||
'msg' => 'Success!',
|
||||
'action' => 'onboard'
|
||||
'action' => 'onboard',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -324,7 +333,7 @@ class RemoteAuthController extends Controller
|
|||
'bearer_token' => $token,
|
||||
'verify_credentials' => $res,
|
||||
'last_verify_credentials_at' => now(),
|
||||
'last_successful_login_at' => now()
|
||||
'last_successful_login_at' => now(),
|
||||
]);
|
||||
|
||||
$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))) {
|
||||
return $fail('Username cannot be used.');
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
]);
|
||||
$username = strtolower($request->input('username'));
|
||||
|
||||
|
@ -390,7 +399,7 @@ class RemoteAuthController extends Controller
|
|||
return response()->json([
|
||||
'code' => 200,
|
||||
'username' => $username,
|
||||
'exists' => $exists
|
||||
'exists' => $exists,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -411,7 +420,7 @@ class RemoteAuthController extends Controller
|
|||
'email' => [
|
||||
'required',
|
||||
'email:strict,filter_unicode,dns,spoof',
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$email = $request->input('email');
|
||||
|
@ -422,7 +431,7 @@ class RemoteAuthController extends Controller
|
|||
'code' => 200,
|
||||
'email' => $email,
|
||||
'exists' => $exists,
|
||||
'banned' => $banned
|
||||
'banned' => $banned,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -448,7 +457,7 @@ class RemoteAuthController extends Controller
|
|||
if (! $res) {
|
||||
return response()->json([
|
||||
'code' => 200,
|
||||
'following' => []
|
||||
'following' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -456,7 +465,7 @@ class RemoteAuthController extends Controller
|
|||
|
||||
return response()->json([
|
||||
'code' => 200,
|
||||
'following' => $res
|
||||
'following' => $res,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -512,10 +521,10 @@ class RemoteAuthController extends Controller
|
|||
if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
|
||||
return $fail('Username cannot be used.');
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
'password' => 'required|string|min:8|confirmed',
|
||||
'name' => 'nullable|max:30'
|
||||
'name' => 'nullable|max:30',
|
||||
]);
|
||||
|
||||
$email = $request->input('email');
|
||||
|
@ -527,7 +536,7 @@ class RemoteAuthController extends Controller
|
|||
'name' => $name,
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
'email' => $email
|
||||
'email' => $email,
|
||||
]);
|
||||
|
||||
$raid = $request->session()->pull('oauth_masto_raid');
|
||||
|
@ -541,7 +550,7 @@ class RemoteAuthController extends Controller
|
|||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Success',
|
||||
'token' => $token
|
||||
'token' => $token,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -585,7 +594,7 @@ class RemoteAuthController extends Controller
|
|||
abort_unless($request->session()->exists('oauth_remasto_id'), 403);
|
||||
|
||||
$this->validate($request, [
|
||||
'account' => 'required|url'
|
||||
'account' => 'required|url',
|
||||
]);
|
||||
|
||||
$account = $request->input('account');
|
||||
|
@ -641,7 +650,7 @@ class RemoteAuthController extends Controller
|
|||
$avatar->remote_url = $request->input('avatar_url');
|
||||
$avatar->save();
|
||||
|
||||
MediaStorageService::avatar($avatar, config_cache('pixelfed.cloud_storage') == false);
|
||||
MediaStorageService::avatar($avatar, (bool) config_cache('pixelfed.cloud_storage') == false);
|
||||
|
||||
return [200];
|
||||
}
|
||||
|
@ -691,6 +700,7 @@ class RemoteAuthController extends Controller
|
|||
$user = User::findOrFail($ra->user_id);
|
||||
abort_if($user->is_admin || $user->status != null, 422, 'Invalid auth action');
|
||||
Auth::loginUsingId($ra->user_id);
|
||||
|
||||
return [200];
|
||||
}
|
||||
|
||||
|
@ -703,7 +713,7 @@ class RemoteAuthController extends Controller
|
|||
'password' => Hash::make($data['password']),
|
||||
'email_verified_at' => config('remote-auth.mastodon.contraints.skip_email_verification') ? now() : null,
|
||||
'app_register_ip' => request()->ip(),
|
||||
'register_source' => 'mastodon'
|
||||
'register_source' => 'mastodon',
|
||||
])));
|
||||
|
||||
$this->guarder()->login($user);
|
||||
|
|
|
@ -2,27 +2,25 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use App\Hashtag;
|
||||
use App\Place;
|
||||
use App\Profile;
|
||||
use App\Services\WebfingerService;
|
||||
use App\Status;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Util\ActivityPub\Helpers;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Transformer\Api\{
|
||||
AccountTransformer,
|
||||
HashtagTransformer,
|
||||
StatusTransformer,
|
||||
};
|
||||
use App\Services\WebfingerService;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
public $tokens = [];
|
||||
|
||||
public $term = '';
|
||||
|
||||
public $hash = '';
|
||||
|
||||
public $cacheKey = 'api:search:tag:';
|
||||
|
||||
public function __construct()
|
||||
|
@ -36,7 +34,7 @@ class SearchController extends Controller
|
|||
'q' => 'required|string|min:3|max:120',
|
||||
'src' => 'required|string|in:metro',
|
||||
'v' => 'required|integer|in:2',
|
||||
'scope' => 'required|in:all,hashtag,profile,remote,webfinger'
|
||||
'scope' => 'required|in:all,hashtag,profile,remote,webfinger',
|
||||
]);
|
||||
|
||||
$scope = $request->input('scope') ?? 'all';
|
||||
|
@ -84,12 +82,13 @@ class SearchController extends Controller
|
|||
$hash = hash('sha256', $tag);
|
||||
if (Helpers::validateUrl($tag) != false &&
|
||||
Helpers::validateLocalUrl($tag) != true &&
|
||||
config_cache('federation.activitypub.enabled') == true &&
|
||||
(bool) config_cache('federation.activitypub.enabled') == true &&
|
||||
config('federation.activitypub.remoteFollow') == true
|
||||
) {
|
||||
$remote = Helpers::fetchFromUrl($tag);
|
||||
if (isset($remote['type']) &&
|
||||
$remote['type'] == 'Note') {
|
||||
in_array($remote['type'], ['Note', 'Question'])
|
||||
) {
|
||||
$item = Helpers::statusFetch($tag);
|
||||
$this->tokens['posts'] = [[
|
||||
'count' => 0,
|
||||
|
@ -122,7 +121,7 @@ class SearchController extends Controller
|
|||
'tokens' => [$item->caption],
|
||||
'name' => $item->caption,
|
||||
'thumb' => $item->thumb(),
|
||||
'filter' => $item->firstMedia()->filter_class
|
||||
'filter' => $item->firstMedia()->filter_class,
|
||||
];
|
||||
});
|
||||
$this->tokens['posts'] = $posts;
|
||||
|
@ -153,6 +152,7 @@ class SearchController extends Controller
|
|||
'name' => null,
|
||||
];
|
||||
});
|
||||
|
||||
return $tags;
|
||||
}
|
||||
});
|
||||
|
@ -180,7 +180,7 @@ class SearchController extends Controller
|
|||
'tokens' => '',
|
||||
'name' => null,
|
||||
'city' => $item->name,
|
||||
'country' => $item->country
|
||||
'country' => $item->country,
|
||||
];
|
||||
});
|
||||
// return $tags;
|
||||
|
@ -190,7 +190,7 @@ class SearchController extends Controller
|
|||
$this->tokens['placesPagination'] = [
|
||||
'total' => $hashtags->total(),
|
||||
'current_page' => $hashtags->currentPage(),
|
||||
'last_page' => $hashtags->lastPage()
|
||||
'last_page' => $hashtags->lastPage(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ class SearchController extends Controller
|
|||
$ttl = now()->addHours(2);
|
||||
if (Helpers::validateUrl($tag) != false &&
|
||||
Helpers::validateLocalUrl($tag) != true &&
|
||||
config_cache('federation.activitypub.enabled') == true &&
|
||||
(bool) config_cache('federation.activitypub.enabled') == true &&
|
||||
config('federation.activitypub.remoteFollow') == true
|
||||
) {
|
||||
$remote = Helpers::fetchFromUrl($tag);
|
||||
|
@ -225,15 +225,14 @@ class SearchController extends Controller
|
|||
'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
|
||||
'thumb' => $item->avatarUrl(),
|
||||
'local' => (bool) ! $item->domain,
|
||||
'post_count' => $item->statuses()->count()
|
||||
]
|
||||
'post_count' => $item->statuses()->count(),
|
||||
],
|
||||
]];
|
||||
|
||||
return $tokens;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
$this->tokens['profiles'] = Cache::remember($key, $ttl, function () use ($tag) {
|
||||
if (Str::startsWith($tag, '@')) {
|
||||
$tag = substr($tag, 1);
|
||||
|
@ -262,8 +261,8 @@ class SearchController extends Controller
|
|||
'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
|
||||
'thumb' => $item->avatarUrl(),
|
||||
'local' => (bool) ! $item->domain,
|
||||
'post_count' => $item->statuses()->count()
|
||||
]
|
||||
'post_count' => $item->statuses()->count(),
|
||||
],
|
||||
];
|
||||
});
|
||||
}
|
||||
|
@ -301,11 +300,11 @@ class SearchController extends Controller
|
|||
'following' => null,
|
||||
'follow_request' => null,
|
||||
'thumb' => $wfs['avatar'],
|
||||
'local' => (bool) $wfs['local']
|
||||
]
|
||||
]
|
||||
'local' => (bool) $wfs['local'],
|
||||
],
|
||||
],
|
||||
];
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
protected function remotePostLookup()
|
||||
|
@ -333,7 +332,7 @@ class SearchController extends Controller
|
|||
'username' => $item->profile->username,
|
||||
'caption' => $item->rendered ?? $item->caption,
|
||||
'thumb' => $url,
|
||||
'timestamp' => $item->created_at->diffForHumans()
|
||||
'timestamp' => $item->created_at->diffForHumans(),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -353,7 +352,7 @@ class SearchController extends Controller
|
|||
'username' => $item->profile->username,
|
||||
'caption' => $item->rendered ?? $item->caption,
|
||||
'thumb' => $url,
|
||||
'timestamp' => $item->created_at->diffForHumans()
|
||||
'timestamp' => $item->created_at->diffForHumans(),
|
||||
]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ class StatusController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
if ($request->wantsJson() && config_cache('federation.activitypub.enabled')) {
|
||||
if ($request->wantsJson() && (bool) config_cache('federation.activitypub.enabled')) {
|
||||
return $this->showActivityPub($request, $status);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,34 +2,35 @@
|
|||
|
||||
namespace App\Http\Controllers\Stories;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Models\Conversation;
|
||||
use App\DirectMessage;
|
||||
use App\Notification;
|
||||
use App\Story;
|
||||
use App\Status;
|
||||
use App\StoryView;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\StoryView as StoryViewResource;
|
||||
use App\Jobs\StoryPipeline\StoryDelete;
|
||||
use App\Jobs\StoryPipeline\StoryFanout;
|
||||
use App\Jobs\StoryPipeline\StoryReplyDeliver;
|
||||
use App\Jobs\StoryPipeline\StoryViewDeliver;
|
||||
use App\Models\Conversation;
|
||||
use App\Notification;
|
||||
use App\Services\AccountService;
|
||||
use App\Services\MediaPathService;
|
||||
use App\Services\StoryService;
|
||||
use App\Http\Resources\StoryView as StoryViewResource;
|
||||
use App\Status;
|
||||
use App\Story;
|
||||
use App\StoryView;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StoryApiV1Controller extends Controller
|
||||
{
|
||||
const RECENT_KEY = 'pf:stories:recent-by-id:';
|
||||
|
||||
const RECENT_TTL = 300;
|
||||
|
||||
public function carousel(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$pid = $request->user()->profile_id;
|
||||
|
||||
if (config('database.default') == 'pgsql') {
|
||||
|
@ -44,6 +45,7 @@ class StoryApiV1Controller extends Controller
|
|||
$r->profile_id = $s->profile_id;
|
||||
$r->type = $s->type;
|
||||
$r->path = $s->path;
|
||||
|
||||
return $r;
|
||||
})
|
||||
->unique('profile_id');
|
||||
|
@ -72,7 +74,7 @@ class StoryApiV1Controller extends Controller
|
|||
'src' => url(Storage::url($s->path)),
|
||||
'duration' => $s->duration ?? 3,
|
||||
'seen' => StoryService::hasSeen($pid, $s->id),
|
||||
'created_at' => $s->created_at->format('c')
|
||||
'created_at' => $s->created_at->format('c'),
|
||||
];
|
||||
})
|
||||
->filter()
|
||||
|
@ -81,6 +83,7 @@ class StoryApiV1Controller extends Controller
|
|||
$profile = AccountService::get($item[0]['pid'], true);
|
||||
$url = $profile['local'] ? url("/stories/{$profile['username']}") :
|
||||
url("/i/rs/{$profile['id']}");
|
||||
|
||||
return [
|
||||
'id' => 'pfs:'.$profile['id'],
|
||||
'user' => [
|
||||
|
@ -89,7 +92,7 @@ class StoryApiV1Controller extends Controller
|
|||
'username_acct' => $profile['acct'],
|
||||
'avatar' => $profile['avatar'],
|
||||
'local' => $profile['local'],
|
||||
'is_author' => $profile['id'] == $pid
|
||||
'is_author' => $profile['id'] == $pid,
|
||||
],
|
||||
'nodes' => $item,
|
||||
'url' => $url,
|
||||
|
@ -108,14 +111,14 @@ class StoryApiV1Controller extends Controller
|
|||
$selfStories = Story::whereProfileId($pid)
|
||||
->whereActive(true)
|
||||
->get()
|
||||
->map(function($s) use($pid) {
|
||||
->map(function ($s) {
|
||||
return [
|
||||
'id' => (string) $s->id,
|
||||
'type' => $s->type,
|
||||
'src' => url(Storage::url($s->path)),
|
||||
'duration' => $s->duration,
|
||||
'seen' => true,
|
||||
'created_at' => $s->created_at->format('c')
|
||||
'created_at' => $s->created_at->format('c'),
|
||||
];
|
||||
})
|
||||
->sortBy('id')
|
||||
|
@ -127,18 +130,19 @@ class StoryApiV1Controller extends Controller
|
|||
'username' => $selfProfile['acct'],
|
||||
'avatar' => $selfProfile['avatar'],
|
||||
'local' => $selfProfile['local'],
|
||||
'is_author' => true
|
||||
'is_author' => true,
|
||||
],
|
||||
|
||||
'nodes' => $selfStories,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
public function selfCarousel(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$pid = $request->user()->profile_id;
|
||||
|
||||
if (config('database.default') == 'pgsql') {
|
||||
|
@ -153,6 +157,7 @@ class StoryApiV1Controller extends Controller
|
|||
$r->profile_id = $s->profile_id;
|
||||
$r->type = $s->type;
|
||||
$r->path = $s->path;
|
||||
|
||||
return $r;
|
||||
})
|
||||
->unique('profile_id');
|
||||
|
@ -181,7 +186,7 @@ class StoryApiV1Controller extends Controller
|
|||
'src' => url(Storage::url($s->path)),
|
||||
'duration' => $s->duration ?? 3,
|
||||
'seen' => StoryService::hasSeen($pid, $s->id),
|
||||
'created_at' => $s->created_at->format('c')
|
||||
'created_at' => $s->created_at->format('c'),
|
||||
];
|
||||
})
|
||||
->filter()
|
||||
|
@ -190,6 +195,7 @@ class StoryApiV1Controller extends Controller
|
|||
$profile = AccountService::get($item[0]['pid'], true);
|
||||
$url = $profile['local'] ? url("/stories/{$profile['username']}") :
|
||||
url("/i/rs/{$profile['id']}");
|
||||
|
||||
return [
|
||||
'id' => 'pfs:'.$profile['id'],
|
||||
'user' => [
|
||||
|
@ -198,7 +204,7 @@ class StoryApiV1Controller extends Controller
|
|||
'username_acct' => $profile['acct'],
|
||||
'avatar' => $profile['avatar'],
|
||||
'local' => $profile['local'],
|
||||
'is_author' => $profile['id'] == $pid
|
||||
'is_author' => $profile['id'] == $pid,
|
||||
],
|
||||
'nodes' => $item,
|
||||
'url' => $url,
|
||||
|
@ -216,7 +222,7 @@ class StoryApiV1Controller extends Controller
|
|||
'username' => $selfProfile['acct'],
|
||||
'avatar' => $selfProfile['avatar'],
|
||||
'local' => $selfProfile['local'],
|
||||
'is_author' => true
|
||||
'is_author' => true,
|
||||
],
|
||||
|
||||
'nodes' => [],
|
||||
|
@ -228,26 +234,27 @@ class StoryApiV1Controller extends Controller
|
|||
$selfStories = Story::whereProfileId($pid)
|
||||
->whereActive(true)
|
||||
->get()
|
||||
->map(function($s) use($pid) {
|
||||
->map(function ($s) {
|
||||
return [
|
||||
'id' => (string) $s->id,
|
||||
'type' => $s->type,
|
||||
'src' => url(Storage::url($s->path)),
|
||||
'duration' => $s->duration,
|
||||
'seen' => true,
|
||||
'created_at' => $s->created_at->format('c')
|
||||
'created_at' => $s->created_at->format('c'),
|
||||
];
|
||||
})
|
||||
->sortBy('id')
|
||||
->values();
|
||||
$res['self']['nodes'] = $selfStories;
|
||||
}
|
||||
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
public function add(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'file' => function () {
|
||||
|
@ -257,7 +264,7 @@ class StoryApiV1Controller extends Controller
|
|||
'max:'.config_cache('pixelfed.max_photo_size'),
|
||||
];
|
||||
},
|
||||
'duration' => 'sometimes|integer|min:0|max:30'
|
||||
'duration' => 'sometimes|integer|min:0|max:30',
|
||||
]);
|
||||
|
||||
$user = $request->user();
|
||||
|
@ -293,7 +300,7 @@ class StoryApiV1Controller extends Controller
|
|||
'msg' => 'Successfully added',
|
||||
'media_id' => (string) $story->id,
|
||||
'media_url' => url(Storage::url($url)).'?v='.time(),
|
||||
'media_type' => $story->type
|
||||
'media_type' => $story->type,
|
||||
];
|
||||
|
||||
return $res;
|
||||
|
@ -301,13 +308,13 @@ class StoryApiV1Controller extends Controller
|
|||
|
||||
public function publish(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'media_id' => 'required',
|
||||
'duration' => 'required|integer|min:0|max:30',
|
||||
'can_reply' => 'required|boolean',
|
||||
'can_react' => 'required|boolean'
|
||||
'can_react' => 'required|boolean',
|
||||
]);
|
||||
|
||||
$id = $request->input('media_id');
|
||||
|
@ -333,7 +340,7 @@ class StoryApiV1Controller extends Controller
|
|||
|
||||
public function delete(Request $request, $id)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$user = $request->user();
|
||||
|
||||
|
@ -346,13 +353,13 @@ class StoryApiV1Controller extends Controller
|
|||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Successfully deleted'
|
||||
'msg' => 'Successfully deleted',
|
||||
];
|
||||
}
|
||||
|
||||
public function viewed(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'id' => 'required|min:1',
|
||||
|
@ -376,7 +383,7 @@ class StoryApiV1Controller extends Controller
|
|||
|
||||
$v = StoryView::firstOrCreate([
|
||||
'story_id' => $id,
|
||||
'profile_id' => $authed->id
|
||||
'profile_id' => $authed->id,
|
||||
]);
|
||||
|
||||
if ($v->wasRecentlyCreated) {
|
||||
|
@ -389,15 +396,16 @@ class StoryApiV1Controller extends Controller
|
|||
|
||||
Cache::forget('stories:recent:by_id:'.$authed->id);
|
||||
StoryService::addSeen($authed->id, $story->id);
|
||||
|
||||
return ['code' => 200];
|
||||
}
|
||||
|
||||
public function comment(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$this->validate($request, [
|
||||
'sid' => 'required',
|
||||
'caption' => 'required|string'
|
||||
'caption' => 'required|string',
|
||||
]);
|
||||
$pid = $request->user()->profile_id;
|
||||
$text = $request->input('caption');
|
||||
|
@ -415,7 +423,7 @@ class StoryApiV1Controller extends Controller
|
|||
$status->visibility = 'direct';
|
||||
$status->in_reply_to_profile_id = $story->profile_id;
|
||||
$status->entities = json_encode([
|
||||
'story_id' => $story->id
|
||||
'story_id' => $story->id,
|
||||
]);
|
||||
$status->save();
|
||||
|
||||
|
@ -429,20 +437,20 @@ class StoryApiV1Controller extends Controller
|
|||
'story_actor_username' => $request->user()->username,
|
||||
'story_id' => $story->id,
|
||||
'story_media_url' => url(Storage::url($story->path)),
|
||||
'caption' => $text
|
||||
'caption' => $text,
|
||||
]);
|
||||
$dm->save();
|
||||
|
||||
Conversation::updateOrInsert(
|
||||
[
|
||||
'to_id' => $story->profile_id,
|
||||
'from_id' => $pid
|
||||
'from_id' => $pid,
|
||||
],
|
||||
[
|
||||
'type' => 'story:comment',
|
||||
'status_id' => $status->id,
|
||||
'dm_id' => $dm->id,
|
||||
'is_hidden' => false
|
||||
'is_hidden' => false,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -460,7 +468,7 @@ class StoryApiV1Controller extends Controller
|
|||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Sent!'
|
||||
'msg' => 'Sent!',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -470,23 +478,25 @@ class StoryApiV1Controller extends Controller
|
|||
if (in_array($photo->getMimeType(), [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'video/mp4'
|
||||
'video/mp4',
|
||||
]) == false) {
|
||||
abort(400, 'Invalid media type');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$storagePath = MediaPathService::story($user->profile);
|
||||
$path = $photo->storePubliclyAs($storagePath, Str::random(random_int(2, 12)).'_'.Str::random(random_int(32, 35)).'_'.Str::random(random_int(1, 14)).'.'.$photo->extension());
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function viewers(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'sid' => 'required|string|min:1|max:50'
|
||||
'sid' => 'required|string|min:1|max:50',
|
||||
]);
|
||||
|
||||
$pid = $request->user()->profile_id;
|
||||
|
|
|
@ -2,40 +2,33 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Media;
|
||||
use App\Profile;
|
||||
use App\Report;
|
||||
use App\DirectMessage;
|
||||
use App\Notification;
|
||||
use App\Status;
|
||||
use App\Story;
|
||||
use App\StoryView;
|
||||
use App\Models\Poll;
|
||||
use App\Models\PollVote;
|
||||
use App\Services\ProfileService;
|
||||
use App\Services\StoryService;
|
||||
use Cache, Storage;
|
||||
use Image as Intervention;
|
||||
use App\Services\FollowerService;
|
||||
use App\Services\MediaPathService;
|
||||
use FFMpeg;
|
||||
use FFMpeg\Coordinate\Dimension;
|
||||
use FFMpeg\Format\Video\X264;
|
||||
use App\Jobs\StoryPipeline\StoryDelete;
|
||||
use App\Jobs\StoryPipeline\StoryFanout;
|
||||
use App\Jobs\StoryPipeline\StoryReactionDeliver;
|
||||
use App\Jobs\StoryPipeline\StoryReplyDeliver;
|
||||
use App\Jobs\StoryPipeline\StoryFanout;
|
||||
use App\Jobs\StoryPipeline\StoryDelete;
|
||||
use ImageOptimizer;
|
||||
use App\Models\Conversation;
|
||||
use App\Models\Poll;
|
||||
use App\Models\PollVote;
|
||||
use App\Notification;
|
||||
use App\Report;
|
||||
use App\Services\FollowerService;
|
||||
use App\Services\MediaPathService;
|
||||
use App\Services\StoryService;
|
||||
use App\Services\UserRoleService;
|
||||
use App\Status;
|
||||
use App\Story;
|
||||
use FFMpeg;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Image as Intervention;
|
||||
use Storage;
|
||||
|
||||
class StoryComposeController extends Controller
|
||||
{
|
||||
public function apiV1Add(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'file' => function () {
|
||||
|
@ -80,7 +73,7 @@ class StoryComposeController extends Controller
|
|||
'msg' => 'Successfully added',
|
||||
'media_id' => (string) $story->id,
|
||||
'media_url' => url(Storage::url($url)).'?v='.time(),
|
||||
'media_type' => $story->type
|
||||
'media_type' => $story->type,
|
||||
];
|
||||
|
||||
if ($story->type === 'video') {
|
||||
|
@ -90,8 +83,9 @@ class StoryComposeController extends Controller
|
|||
if ($duration > 500) {
|
||||
Storage::delete($story->path);
|
||||
$story->delete();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Video duration cannot exceed 60 seconds'
|
||||
'message' => 'Video duration cannot exceed 60 seconds',
|
||||
], 422);
|
||||
}
|
||||
}
|
||||
|
@ -105,9 +99,10 @@ class StoryComposeController extends Controller
|
|||
if (in_array($photo->getMimeType(), [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'video/mp4'
|
||||
'video/mp4',
|
||||
]) == false) {
|
||||
abort(400, 'Invalid media type');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -120,19 +115,20 @@ class StoryComposeController extends Controller
|
|||
$img->save($fpath, config_cache('pixelfed.image_quality'));
|
||||
$img->destroy();
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function cropPhoto(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'media_id' => 'required|integer|min:1',
|
||||
'width' => 'required',
|
||||
'height' => 'required',
|
||||
'x' => 'required',
|
||||
'y' => 'required'
|
||||
'y' => 'required',
|
||||
]);
|
||||
|
||||
$user = $request->user();
|
||||
|
@ -167,13 +163,13 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function publishStory(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'media_id' => 'required',
|
||||
'duration' => 'required|integer|min:3|max:120',
|
||||
'can_reply' => 'required|boolean',
|
||||
'can_react' => 'required|boolean'
|
||||
'can_react' => 'required|boolean',
|
||||
]);
|
||||
|
||||
$id = $request->input('media_id');
|
||||
|
@ -200,7 +196,7 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function apiV1Delete(Request $request, $id)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$user = $request->user();
|
||||
|
||||
|
@ -213,13 +209,13 @@ class StoryComposeController extends Controller
|
|||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Successfully deleted'
|
||||
'msg' => 'Successfully deleted',
|
||||
];
|
||||
}
|
||||
|
||||
public function compose(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$user = $request->user();
|
||||
abort_if($user->has_roles && ! UserRoleService::can('can-use-stories', $user->id), 403, 'Invalid permissions for this action');
|
||||
|
||||
|
@ -228,7 +224,7 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function createPoll(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
abort_if(! config_cache('instance.polls.enabled'), 404);
|
||||
|
||||
return $request->all();
|
||||
|
@ -236,13 +232,13 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function publishStoryPoll(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'question' => 'required|string|min:6|max:140',
|
||||
'options' => 'required|array|min:2|max:4',
|
||||
'can_reply' => 'required|boolean',
|
||||
'can_react' => 'required|boolean'
|
||||
'can_react' => 'required|boolean',
|
||||
]);
|
||||
|
||||
$user = $request->user();
|
||||
|
@ -262,7 +258,7 @@ class StoryComposeController extends Controller
|
|||
$story->type = 'poll';
|
||||
$story->story = json_encode([
|
||||
'question' => $request->input('question'),
|
||||
'options' => $request->input('options')
|
||||
'options' => $request->input('options'),
|
||||
]);
|
||||
$story->public = false;
|
||||
$story->local = true;
|
||||
|
@ -296,11 +292,11 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function storyPollVote(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'sid' => 'required',
|
||||
'ci' => 'required|integer|min:0|max:3'
|
||||
'ci' => 'required|integer|min:0|max:3',
|
||||
]);
|
||||
|
||||
$pid = $request->user()->profile_id;
|
||||
|
@ -328,7 +324,7 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function storeReport(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'type' => 'required|alpha_dash',
|
||||
|
@ -353,7 +349,7 @@ class StoryComposeController extends Controller
|
|||
'copyright',
|
||||
'impersonation',
|
||||
'scam',
|
||||
'terrorism'
|
||||
'terrorism',
|
||||
];
|
||||
|
||||
abort_if(! in_array($type, $types), 422, 'Invalid story report type');
|
||||
|
@ -370,7 +366,7 @@ class StoryComposeController extends Controller
|
|||
) {
|
||||
return response()->json(['error' => [
|
||||
'code' => 409,
|
||||
'message' => 'Cannot report the same story again'
|
||||
'message' => 'Cannot report the same story again',
|
||||
]], 409);
|
||||
}
|
||||
|
||||
|
@ -389,10 +385,10 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function react(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$this->validate($request, [
|
||||
'sid' => 'required',
|
||||
'reaction' => 'required|string'
|
||||
'reaction' => 'required|string',
|
||||
]);
|
||||
$pid = $request->user()->profile_id;
|
||||
$text = $request->input('reaction');
|
||||
|
@ -413,7 +409,7 @@ class StoryComposeController extends Controller
|
|||
$status->in_reply_to_profile_id = $story->profile_id;
|
||||
$status->entities = json_encode([
|
||||
'story_id' => $story->id,
|
||||
'reaction' => $text
|
||||
'reaction' => $text,
|
||||
]);
|
||||
$status->save();
|
||||
|
||||
|
@ -427,20 +423,20 @@ class StoryComposeController extends Controller
|
|||
'story_actor_username' => $request->user()->username,
|
||||
'story_id' => $story->id,
|
||||
'story_media_url' => url(Storage::url($story->path)),
|
||||
'reaction' => $text
|
||||
'reaction' => $text,
|
||||
]);
|
||||
$dm->save();
|
||||
|
||||
Conversation::updateOrInsert(
|
||||
[
|
||||
'to_id' => $story->profile_id,
|
||||
'from_id' => $pid
|
||||
'from_id' => $pid,
|
||||
],
|
||||
[
|
||||
'type' => 'story:react',
|
||||
'status_id' => $status->id,
|
||||
'dm_id' => $dm->id,
|
||||
'is_hidden' => false
|
||||
'is_hidden' => false,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -464,10 +460,10 @@ class StoryComposeController extends Controller
|
|||
|
||||
public function comment(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
|
||||
$this->validate($request, [
|
||||
'sid' => 'required',
|
||||
'caption' => 'required|string'
|
||||
'caption' => 'required|string',
|
||||
]);
|
||||
$pid = $request->user()->profile_id;
|
||||
$text = $request->input('caption');
|
||||
|
@ -486,7 +482,7 @@ class StoryComposeController extends Controller
|
|||
$status->visibility = 'direct';
|
||||
$status->in_reply_to_profile_id = $story->profile_id;
|
||||
$status->entities = json_encode([
|
||||
'story_id' => $story->id
|
||||
'story_id' => $story->id,
|
||||
]);
|
||||
$status->save();
|
||||
|
||||
|
@ -500,20 +496,20 @@ class StoryComposeController extends Controller
|
|||
'story_actor_username' => $request->user()->username,
|
||||
'story_id' => $story->id,
|
||||
'story_media_url' => url(Storage::url($story->path)),
|
||||
'caption' => $text
|
||||
'caption' => $text,
|
||||
]);
|
||||
$dm->save();
|
||||
|
||||
Conversation::updateOrInsert(
|
||||
[
|
||||
'to_id' => $story->profile_id,
|
||||
'from_id' => $pid
|
||||
'from_id' => $pid,
|
||||
],
|
||||
[
|
||||
'type' => 'story:comment',
|
||||
'status_id' => $status->id,
|
||||
'dm_id' => $dm->id,
|
||||
'is_hidden' => false
|
||||
'is_hidden' => false,
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class StoryController extends StoryComposeController
|
|||
{
|
||||
public function recent(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
$user = $request->user();
|
||||
if($user->has_roles && !UserRoleService::can('can-use-stories', $user->id)) {
|
||||
return [];
|
||||
|
@ -117,7 +117,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function profile(Request $request, $id)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$user = $request->user();
|
||||
if($user->has_roles && !UserRoleService::can('can-use-stories', $user->id)) {
|
||||
|
@ -176,7 +176,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function viewed(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'id' => 'required|min:1',
|
||||
|
@ -221,7 +221,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function exists(Request $request, $id)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
$user = $request->user();
|
||||
if($user->has_roles && !UserRoleService::can('can-use-stories', $user->id)) {
|
||||
return response()->json(false);
|
||||
|
@ -233,7 +233,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function iRedirect(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$user = $request->user();
|
||||
abort_if(!$user, 404);
|
||||
|
@ -243,7 +243,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function viewers(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'sid' => 'required|string'
|
||||
|
@ -274,7 +274,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function remoteStory(Request $request, $id)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$profile = Profile::findOrFail($id);
|
||||
if($profile->user_id != null || $profile->domain == null) {
|
||||
|
@ -286,7 +286,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function pollResults(Request $request)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'sid' => 'required|string'
|
||||
|
@ -304,7 +304,7 @@ class StoryController extends StoryComposeController
|
|||
|
||||
public function getActivityObject(Request $request, $username, $id)
|
||||
{
|
||||
abort_if(!config_cache('instance.stories.enabled'), 404);
|
||||
abort_if(!(bool) config_cache('instance.stories.enabled'), 404);
|
||||
|
||||
if(!$request->wantsJson()) {
|
||||
return redirect('/stories/' . $username);
|
||||
|
|
|
@ -34,7 +34,7 @@ class UserEmailForgotController extends Controller
|
|||
'username.exists' => 'This username is no longer active or does not exist!'
|
||||
];
|
||||
|
||||
if(config('captcha.enabled') || config('captcha.active.login') || config('captcha.active.register')) {
|
||||
if((bool) config_cache('captcha.enabled')) {
|
||||
$rules['h-captcha-response'] = 'required|captcha';
|
||||
$messages['h-captcha-response.required'] = 'You need to complete the captcha!';
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace App\Http\Requests\Status;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use App\Media;
|
||||
use App\Status;
|
||||
use Closure;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStatusEditRequest extends FormRequest
|
||||
{
|
||||
|
@ -22,16 +22,17 @@ class StoreStatusEditRequest extends FormRequest
|
|||
return false;
|
||||
}
|
||||
$types = [
|
||||
"photo",
|
||||
"photo:album",
|
||||
"photo:video:album",
|
||||
"reply",
|
||||
"text",
|
||||
"video",
|
||||
"video:album"
|
||||
'photo',
|
||||
'photo:album',
|
||||
'photo:video:album',
|
||||
'reply',
|
||||
'text',
|
||||
'video',
|
||||
'video:album',
|
||||
];
|
||||
$scopes = ['public', 'unlisted', 'private'];
|
||||
$status = Status::whereNull('reblog_of_id')->whereIn('type', $types)->whereIn('scope', $scopes)->find($this->route('id'));
|
||||
|
||||
return $status && $this->user()->profile_id === $status->profile_id;
|
||||
}
|
||||
|
||||
|
@ -50,7 +51,7 @@ class StoreStatusEditRequest extends FormRequest
|
|||
'nullable',
|
||||
'required_without:status',
|
||||
'array',
|
||||
'max:' . config('pixelfed.max_album_length'),
|
||||
'max:'.(int) config_cache('pixelfed.max_album_length'),
|
||||
function (string $attribute, mixed $value, Closure $fail) {
|
||||
Media::whereProfileId($this->user()->profile_id)
|
||||
->where(function ($query) {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace App\Jobs\AvatarPipeline;
|
||||
|
||||
use Cache;
|
||||
use App\Avatar;
|
||||
use App\Profile;
|
||||
use Cache;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
@ -20,6 +20,7 @@ class AvatarOptimize implements ShouldQueue
|
|||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $profile;
|
||||
|
||||
protected $current;
|
||||
|
||||
/**
|
||||
|
@ -65,7 +66,7 @@ class AvatarOptimize implements ShouldQueue
|
|||
Cache::forget('avatar:'.$avatar->profile_id);
|
||||
$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);
|
||||
} else {
|
||||
$avatar->cdn_url = null;
|
||||
|
@ -79,8 +80,7 @@ class AvatarOptimize implements ShouldQueue
|
|||
{
|
||||
if (storage_path('app/'.$new) == $current ||
|
||||
Str::endsWith($current, 'avatars/default.png') ||
|
||||
Str::endsWith($current, 'avatars/default.jpg'))
|
||||
{
|
||||
Str::endsWith($current, 'avatars/default.jpg')) {
|
||||
return;
|
||||
}
|
||||
if (is_file($current)) {
|
||||
|
|
|
@ -4,20 +4,13 @@ namespace App\Jobs\AvatarPipeline;
|
|||
|
||||
use App\Avatar;
|
||||
use App\Profile;
|
||||
use App\Services\MediaStorageService;
|
||||
use App\Util\ActivityPub\Helpers;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
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
|
||||
{
|
||||
|
@ -38,7 +31,9 @@ class RemoteAvatarFetch implements ShouldQueue
|
|||
* @var int
|
||||
*/
|
||||
public $tries = 1;
|
||||
|
||||
public $timeout = 300;
|
||||
|
||||
public $maxExceptions = 1;
|
||||
|
||||
/**
|
||||
|
@ -60,7 +55,7 @@ class RemoteAvatarFetch implements ShouldQueue
|
|||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
|
@ -108,7 +103,7 @@ class RemoteAvatarFetch implements ShouldQueue
|
|||
$avatar->remote_url = $icon['url'];
|
||||
$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;
|
||||
}
|
||||
|
|
|
@ -4,28 +4,21 @@ namespace App\Jobs\AvatarPipeline;
|
|||
|
||||
use App\Avatar;
|
||||
use App\Profile;
|
||||
use App\Services\AccountService;
|
||||
use App\Services\MediaStorageService;
|
||||
use Cache;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
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
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $profile;
|
||||
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
|
@ -41,7 +34,9 @@ class RemoteAvatarFetchFromUrl implements ShouldQueue
|
|||
* @var int
|
||||
*/
|
||||
public $tries = 1;
|
||||
|
||||
public $timeout = 300;
|
||||
|
||||
public $maxExceptions = 1;
|
||||
|
||||
/**
|
||||
|
@ -67,7 +62,7 @@ class RemoteAvatarFetchFromUrl implements ShouldQueue
|
|||
Cache::forget('avatar:'.$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;
|
||||
}
|
||||
|
||||
|
@ -89,7 +84,7 @@ class RemoteAvatarFetchFromUrl implements ShouldQueue
|
|||
$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;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class ImageOptimize implements ShouldQueue
|
|||
return;
|
||||
}
|
||||
|
||||
if(config('pixelfed.optimize_image') == false) {
|
||||
if((bool) config_cache('pixelfed.optimize_image') == false) {
|
||||
ImageThumbnail::dispatch($media)->onQueue('mmo');
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -51,7 +51,7 @@ class ImageResize implements ShouldQueue
|
|||
return;
|
||||
}
|
||||
|
||||
if(!config('pixelfed.optimize_image')) {
|
||||
if((bool) config_cache('pixelfed.optimize_image') === false) {
|
||||
ImageThumbnail::dispatch($media)->onQueue('mmo');
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class ImageUpdate implements ShouldQueue
|
|||
return;
|
||||
}
|
||||
|
||||
if(config('pixelfed.optimize_image')) {
|
||||
if((bool) config_cache('pixelfed.optimize_image')) {
|
||||
if (in_array($media->mime, $this->protectedMimes) == true) {
|
||||
ImageOptimizer::optimize($thumb);
|
||||
if(!$media->skip_optimize) {
|
||||
|
|
|
@ -3,27 +3,30 @@
|
|||
namespace App\Jobs\MediaPipeline;
|
||||
|
||||
use App\Media;
|
||||
use App\Services\Media\MediaHlsService;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
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\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;
|
||||
|
||||
protected $media;
|
||||
|
||||
public $timeout = 300;
|
||||
|
||||
public $tries = 3;
|
||||
|
||||
public $maxExceptions = 1;
|
||||
|
||||
public $failOnTimeout = true;
|
||||
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
/**
|
||||
|
@ -70,7 +73,7 @@ class MediaDeletePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing
|
|||
array_pop($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'));
|
||||
|
||||
if ($path && $disk->exists($path)) {
|
||||
|
|
|
@ -8,7 +8,6 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
|||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MediaFixLocalFilesystemCleanupPipeline implements ShouldQueue
|
||||
|
@ -16,12 +15,14 @@ class MediaFixLocalFilesystemCleanupPipeline implements ShouldQueue
|
|||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 1800;
|
||||
|
||||
public $tries = 5;
|
||||
|
||||
public $maxExceptions = 1;
|
||||
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use Log;
|
|||
use Storage;
|
||||
use Zttp\Zttp;
|
||||
use App\Util\ActivityPub\Helpers;
|
||||
use App\Services\MediaPathService;
|
||||
|
||||
class RemoteFollowImportRecent implements ShouldQueue
|
||||
{
|
||||
|
@ -45,7 +46,6 @@ class RemoteFollowImportRecent implements ShouldQueue
|
|||
'image/jpg',
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/gif',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -208,9 +208,7 @@ class RemoteFollowImportRecent implements ShouldQueue
|
|||
public function importMedia($url, $mime, $status)
|
||||
{
|
||||
$user = $this->profile;
|
||||
$monthHash = hash('sha1', date('Y').date('m'));
|
||||
$userHash = hash('sha1', $user->id.(string) $user->created_at);
|
||||
$storagePath = "public/m/{$monthHash}/{$userHash}";
|
||||
$storagePath = MediaPathService::get($user, 2);
|
||||
|
||||
try {
|
||||
$info = pathinfo($url);
|
||||
|
|
|
@ -2,9 +2,15 @@
|
|||
|
||||
namespace App\Jobs\SharePipeline;
|
||||
|
||||
use Cache, Log;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use App\{Status, Notification};
|
||||
use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
|
||||
use App\Notification;
|
||||
use App\Services\ReblogService;
|
||||
use App\Services\StatusService;
|
||||
use App\Status;
|
||||
use App\Transformer\ActivityPub\Verb\Announce;
|
||||
use App\Util\ActivityPub\HttpSignature;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Pool;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
@ -12,12 +18,6 @@ use Illuminate\Queue\InteractsWithQueue;
|
|||
use Illuminate\Queue\SerializesModels;
|
||||
use League\Fractal;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
use App\Transformer\ActivityPub\Verb\Announce;
|
||||
use GuzzleHttp\{Pool, Client, Promise};
|
||||
use App\Util\ActivityPub\HttpSignature;
|
||||
use App\Services\ReblogService;
|
||||
use App\Services\StatusService;
|
||||
use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
|
||||
|
||||
class SharePipeline implements ShouldQueue
|
||||
{
|
||||
|
@ -64,6 +64,7 @@ class SharePipeline implements ShouldQueue
|
|||
|
||||
if ($target->id === $status->profile_id) {
|
||||
$this->remoteAnnounceDeliver();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ class SharePipeline implements ShouldQueue
|
|||
|
||||
public function remoteAnnounceDeliver()
|
||||
{
|
||||
if(config('app.env') !== 'production' || config_cache('federation.activitypub.enabled') == false) {
|
||||
if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) {
|
||||
return true;
|
||||
}
|
||||
$status = $this->status;
|
||||
|
@ -111,7 +112,7 @@ class SharePipeline implements ShouldQueue
|
|||
$payload = json_encode($activity);
|
||||
|
||||
$client = new Client([
|
||||
'timeout' => config('federation.activitypub.delivery.timeout')
|
||||
'timeout' => config('federation.activitypub.delivery.timeout'),
|
||||
]);
|
||||
|
||||
$version = config('pixelfed.version');
|
||||
|
@ -129,8 +130,8 @@ class SharePipeline implements ShouldQueue
|
|||
'curl' => [
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_HEADER => true
|
||||
]
|
||||
CURLOPT_HEADER => true,
|
||||
],
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
@ -141,7 +142,7 @@ class SharePipeline implements ShouldQueue
|
|||
'fulfilled' => function ($response, $index) {
|
||||
},
|
||||
'rejected' => function ($reason, $index) {
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
$promise = $pool->promise();
|
||||
|
|
|
@ -2,9 +2,15 @@
|
|||
|
||||
namespace App\Jobs\SharePipeline;
|
||||
|
||||
use Cache, Log;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use App\{Status, Notification};
|
||||
use App\Jobs\HomeFeedPipeline\FeedRemovePipeline;
|
||||
use App\Notification;
|
||||
use App\Services\ReblogService;
|
||||
use App\Services\StatusService;
|
||||
use App\Status;
|
||||
use App\Transformer\ActivityPub\Verb\UndoAnnounce;
|
||||
use App\Util\ActivityPub\HttpSignature;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Pool;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
@ -12,17 +18,13 @@ use Illuminate\Queue\InteractsWithQueue;
|
|||
use Illuminate\Queue\SerializesModels;
|
||||
use League\Fractal;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
use App\Transformer\ActivityPub\Verb\UndoAnnounce;
|
||||
use GuzzleHttp\{Pool, Client, Promise};
|
||||
use App\Util\ActivityPub\HttpSignature;
|
||||
use App\Services\ReblogService;
|
||||
use App\Services\StatusService;
|
||||
use App\Jobs\HomeFeedPipeline\FeedRemovePipeline;
|
||||
|
||||
class UndoSharePipeline implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $status;
|
||||
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public function __construct(Status $status)
|
||||
|
@ -64,7 +66,7 @@ class UndoSharePipeline implements ShouldQueue
|
|||
return;
|
||||
}
|
||||
|
||||
if(config('app.env') !== 'production' || config_cache('federation.activitypub.enabled') == false) {
|
||||
if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) {
|
||||
return $status->delete();
|
||||
} else {
|
||||
return $this->remoteAnnounceDeliver();
|
||||
|
@ -73,8 +75,9 @@ class UndoSharePipeline implements ShouldQueue
|
|||
|
||||
public function remoteAnnounceDeliver()
|
||||
{
|
||||
if(config('app.env') !== 'production' || config_cache('federation.activitypub.enabled') == false) {
|
||||
if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) {
|
||||
$status->delete();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -95,7 +98,7 @@ class UndoSharePipeline implements ShouldQueue
|
|||
$payload = json_encode($activity);
|
||||
|
||||
$client = new Client([
|
||||
'timeout' => config('federation.activitypub.delivery.timeout')
|
||||
'timeout' => config('federation.activitypub.delivery.timeout'),
|
||||
]);
|
||||
|
||||
$version = config('pixelfed.version');
|
||||
|
@ -113,8 +116,8 @@ class UndoSharePipeline implements ShouldQueue
|
|||
'curl' => [
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_HEADER => true
|
||||
]
|
||||
CURLOPT_HEADER => true,
|
||||
],
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
@ -125,7 +128,7 @@ class UndoSharePipeline implements ShouldQueue
|
|||
'fulfilled' => function ($response, $index) {
|
||||
},
|
||||
'rejected' => function ($reason, $index) {
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
$promise = $pool->promise();
|
||||
|
|
|
@ -2,41 +2,36 @@
|
|||
|
||||
namespace App\Jobs\StatusPipeline;
|
||||
|
||||
use DB, Cache, Storage;
|
||||
use App\{
|
||||
AccountInterstitial,
|
||||
Bookmark,
|
||||
CollectionItem,
|
||||
DirectMessage,
|
||||
Like,
|
||||
Media,
|
||||
MediaTag,
|
||||
Mention,
|
||||
Notification,
|
||||
Report,
|
||||
Status,
|
||||
StatusArchived,
|
||||
StatusHashtag,
|
||||
StatusView
|
||||
};
|
||||
use App\AccountInterstitial;
|
||||
use App\Bookmark;
|
||||
use App\CollectionItem;
|
||||
use App\DirectMessage;
|
||||
use App\Jobs\MediaPipeline\MediaDeletePipeline;
|
||||
use App\Like;
|
||||
use App\Media;
|
||||
use App\MediaTag;
|
||||
use App\Mention;
|
||||
use App\Notification;
|
||||
use App\Report;
|
||||
use App\Services\CollectionService;
|
||||
use App\Services\NotificationService;
|
||||
use App\Services\StatusService;
|
||||
use App\Status;
|
||||
use App\StatusArchived;
|
||||
use App\StatusHashtag;
|
||||
use App\StatusView;
|
||||
use App\Transformer\ActivityPub\Verb\DeleteNote;
|
||||
use App\Util\ActivityPub\HttpSignature;
|
||||
use Cache;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Pool;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use League\Fractal;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
use App\Transformer\ActivityPub\Verb\DeleteNote;
|
||||
use App\Util\ActivityPub\Helpers;
|
||||
use GuzzleHttp\Pool;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Promise;
|
||||
use App\Util\ActivityPub\HttpSignature;
|
||||
use App\Services\CollectionService;
|
||||
use App\Services\StatusService;
|
||||
use App\Services\NotificationService;
|
||||
use App\Jobs\MediaPipeline\MediaDeletePipeline;
|
||||
|
||||
class StatusDelete implements ShouldQueue
|
||||
{
|
||||
|
@ -52,6 +47,7 @@ class StatusDelete implements ShouldQueue
|
|||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public $timeout = 900;
|
||||
|
||||
public $tries = 2;
|
||||
|
||||
/**
|
||||
|
@ -84,7 +80,7 @@ class StatusDelete implements ShouldQueue
|
|||
|
||||
Cache::forget('pf:atom:user-feed:by-id:'.$status->profile_id);
|
||||
|
||||
if(config_cache('federation.activitypub.enabled') == true) {
|
||||
if ((bool) config_cache('federation.activitypub.enabled') == true) {
|
||||
return $this->fanoutDelete($status);
|
||||
} else {
|
||||
return $this->unlinkRemoveMedia($status);
|
||||
|
@ -101,7 +97,7 @@ class StatusDelete implements ShouldQueue
|
|||
|
||||
if ($status->in_reply_to_id) {
|
||||
$parent = Status::findOrFail($status->in_reply_to_id);
|
||||
--$parent->reply_count;
|
||||
$parent->reply_count--;
|
||||
$parent->save();
|
||||
StatusService::del($parent->id);
|
||||
}
|
||||
|
@ -184,7 +180,7 @@ class StatusDelete implements ShouldQueue
|
|||
$payload = json_encode($activity);
|
||||
|
||||
$client = new Client([
|
||||
'timeout' => config('federation.activitypub.delivery.timeout')
|
||||
'timeout' => config('federation.activitypub.delivery.timeout'),
|
||||
]);
|
||||
|
||||
$version = config('pixelfed.version');
|
||||
|
@ -202,8 +198,8 @@ class StatusDelete implements ShouldQueue
|
|||
'curl' => [
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_HEADER => true
|
||||
]
|
||||
CURLOPT_HEADER => true,
|
||||
],
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
@ -214,7 +210,7 @@ class StatusDelete implements ShouldQueue
|
|||
'fulfilled' => function ($response, $index) {
|
||||
},
|
||||
'rejected' => function ($reason, $index) {
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
$promise = $pool->promise();
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
namespace App\Jobs\StatusPipeline;
|
||||
|
||||
use App\Hashtag;
|
||||
use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
|
||||
use App\Jobs\MentionPipeline\MentionPipeline;
|
||||
use App\Mention;
|
||||
use App\Profile;
|
||||
use App\Services\AdminShadowFilterService;
|
||||
use App\Services\PublicTimelineService;
|
||||
use App\Services\StatusService;
|
||||
use App\Services\UserFilterService;
|
||||
use App\Status;
|
||||
use App\StatusHashtag;
|
||||
use App\Services\PublicTimelineService;
|
||||
use App\Util\Lexer\Autolink;
|
||||
use App\Util\Lexer\Extractor;
|
||||
use App\Util\Sentiment\Bouncer;
|
||||
|
@ -19,18 +23,15 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
|||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Services\StatusService;
|
||||
use App\Services\UserFilterService;
|
||||
use App\Services\AdminShadowFilterService;
|
||||
use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
|
||||
use App\Jobs\HomeFeedPipeline\HashtagInsertFanoutPipeline;
|
||||
|
||||
class StatusEntityLexer implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $status;
|
||||
|
||||
protected $entities;
|
||||
|
||||
protected $autolink;
|
||||
|
||||
/**
|
||||
|
@ -110,9 +111,9 @@ class StatusEntityLexer implements ShouldQueue
|
|||
$slug = str_slug($tag, '-', false);
|
||||
|
||||
$hashtag = Hashtag::firstOrCreate([
|
||||
'slug' => $slug
|
||||
'slug' => $slug,
|
||||
], [
|
||||
'name' => $tag
|
||||
'name' => $tag,
|
||||
]);
|
||||
|
||||
StatusHashtag::firstOrCreate(
|
||||
|
@ -179,10 +180,10 @@ class StatusEntityLexer implements ShouldQueue
|
|||
'photo:album',
|
||||
'video',
|
||||
'video:album',
|
||||
'photo:video:album'
|
||||
'photo:video:album',
|
||||
];
|
||||
|
||||
if(config_cache('pixelfed.bouncer.enabled')) {
|
||||
if ((bool) config_cache('pixelfed.bouncer.enabled')) {
|
||||
Bouncer::get($status);
|
||||
}
|
||||
|
||||
|
@ -200,7 +201,7 @@ class StatusEntityLexer implements ShouldQueue
|
|||
}
|
||||
}
|
||||
|
||||
if(config_cache('federation.activitypub.enabled') == true && config('app.env') == 'production') {
|
||||
if ((bool) config_cache('federation.activitypub.enabled') == true && config('app.env') == 'production') {
|
||||
StatusActivityPubDeliver::dispatch($status);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,19 @@
|
|||
|
||||
namespace App\Jobs\StatusPipeline;
|
||||
|
||||
use App\Media;
|
||||
use App\Models\StatusEdit;
|
||||
use App\ModLog;
|
||||
use App\Profile;
|
||||
use App\Services\StatusService;
|
||||
use App\Status;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Media;
|
||||
use App\ModLog;
|
||||
use App\Profile;
|
||||
use App\Status;
|
||||
use App\Models\StatusEdit;
|
||||
use App\Services\StatusService;
|
||||
use Purify;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Purify;
|
||||
|
||||
class StatusRemoteUpdatePipeline implements ShouldQueue
|
||||
{
|
||||
|
@ -57,7 +56,7 @@ class StatusRemoteUpdatePipeline implements ShouldQueue
|
|||
'spoiler_text' => $status->cw_summary,
|
||||
'is_nsfw' => $status->is_nsfw,
|
||||
'ordered_media_attachment_ids' => $status->media()->orderBy('order')->pluck('id')->toArray(),
|
||||
'created_at' => $status->created_at
|
||||
'created_at' => $status->created_at,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +74,7 @@ class StatusRemoteUpdatePipeline implements ShouldQueue
|
|||
$nm['url']
|
||||
) &&
|
||||
in_array($nm['type'], ['Document', 'Image', 'Video']) &&
|
||||
in_array($nm['mediaType'], explode(',', config('pixelfed.media_types')));
|
||||
in_array($nm['mediaType'], explode(',', config_cache('pixelfed.media_types')));
|
||||
});
|
||||
|
||||
// Skip when no media
|
||||
|
@ -86,7 +85,7 @@ class StatusRemoteUpdatePipeline implements ShouldQueue
|
|||
Media::whereProfileId($status->profile_id)
|
||||
->whereStatusId($status->id)
|
||||
->update([
|
||||
'status_id' => null
|
||||
'status_id' => null,
|
||||
]);
|
||||
|
||||
$nm->each(function ($n, $key) use ($status) {
|
||||
|
@ -96,7 +95,7 @@ class StatusRemoteUpdatePipeline implements ShouldQueue
|
|||
return;
|
||||
}
|
||||
|
||||
if(!in_array($res->header('content-type'), explode(',',config('pixelfed.media_types')))) {
|
||||
if (! in_array($res->header('content-type'), explode(',', config_cache('pixelfed.media_types')))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -167,7 +166,7 @@ class StatusRemoteUpdatePipeline implements ShouldQueue
|
|||
'caption' => $cleaned,
|
||||
'spoiler_text' => $spoiler_text,
|
||||
'is_nsfw' => $sensitive,
|
||||
'ordered_media_attachment_ids' => $mids
|
||||
'ordered_media_attachment_ids' => $mids,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class CustomEmoji extends Model
|
|||
|
||||
public static function scan($text, $activitypub = false)
|
||||
{
|
||||
if(config('federation.custom_emoji.enabled') == false) {
|
||||
if((bool) config_cache('federation.custom_emoji.enabled') == false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
namespace App\Observers;
|
||||
|
||||
use App\Avatar;
|
||||
use App\Services\AccountService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Services\AccountService;
|
||||
|
||||
class AvatarObserver
|
||||
{
|
||||
|
@ -19,7 +19,6 @@ class AvatarObserver
|
|||
/**
|
||||
* Handle the avatar "created" event.
|
||||
*
|
||||
* @param \App\Avatar $avatar
|
||||
* @return void
|
||||
*/
|
||||
public function created(Avatar $avatar)
|
||||
|
@ -30,7 +29,6 @@ class AvatarObserver
|
|||
/**
|
||||
* Handle the avatar "updated" event.
|
||||
*
|
||||
* @param \App\Avatar $avatar
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Avatar $avatar)
|
||||
|
@ -41,7 +39,6 @@ class AvatarObserver
|
|||
/**
|
||||
* Handle the avatar "deleted" event.
|
||||
*
|
||||
* @param \App\Avatar $avatar
|
||||
* @return void
|
||||
*/
|
||||
public function deleted(Avatar $avatar)
|
||||
|
@ -52,7 +49,6 @@ class AvatarObserver
|
|||
/**
|
||||
* Handle the avatar "deleting" event.
|
||||
*
|
||||
* @param \App\Avatar $avatar
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(Avatar $avatar)
|
||||
|
@ -65,7 +61,7 @@ class AvatarObserver
|
|||
@unlink($path);
|
||||
}
|
||||
|
||||
if(config_cache('pixelfed.cloud_storage')) {
|
||||
if ((bool) config_cache('pixelfed.cloud_storage')) {
|
||||
$disk = Storage::disk(config('filesystems.cloud'));
|
||||
$base = Str::startsWith($avatar->media_path, 'cache/avatars/');
|
||||
if ($base && $disk->exists($avatar->media_path)) {
|
||||
|
@ -78,7 +74,6 @@ class AvatarObserver
|
|||
/**
|
||||
* Handle the avatar "restored" event.
|
||||
*
|
||||
* @param \App\Avatar $avatar
|
||||
* @return void
|
||||
*/
|
||||
public function restored(Avatar $avatar)
|
||||
|
@ -89,7 +84,6 @@ class AvatarObserver
|
|||
/**
|
||||
* Handle the avatar "force deleted" event.
|
||||
*
|
||||
* @param \App\Avatar $avatar
|
||||
* @return void
|
||||
*/
|
||||
public function forceDeleted(Avatar $avatar)
|
||||
|
|
|
@ -107,7 +107,7 @@ class UserObserver
|
|||
CreateAvatar::dispatch($profile);
|
||||
});
|
||||
|
||||
if(config_cache('account.autofollow') == true) {
|
||||
if((bool) config_cache('account.autofollow') == true) {
|
||||
$names = config_cache('account.autofollow_usernames');
|
||||
$names = explode(',', $names);
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use Gate;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Laravel\Passport\Passport;
|
||||
use Gate;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot()
|
||||
{
|
||||
if(config('app.env') === 'production' && config('pixelfed.oauth_enabled') == true) {
|
||||
if (config('app.env') === 'production' && (bool) config_cache('pixelfed.oauth_enabled') == true) {
|
||||
Passport::tokensExpireIn(now()->addDays(config('instance.oauth.token_expiration', 356)));
|
||||
Passport::refreshTokensExpireIn(now()->addDays(config('instance.oauth.refresh_expiration', 400)));
|
||||
Passport::enableImplicitGrant();
|
||||
|
@ -38,7 +38,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
'follow' => 'Ability to follow other profiles',
|
||||
'admin:read' => 'Read all data on the server',
|
||||
'admin:write' => 'Modify all data on the server',
|
||||
'push' => 'Receive your push notifications'
|
||||
'push' => 'Receive your push notifications',
|
||||
]);
|
||||
|
||||
Passport::setDefaultScope([
|
||||
|
|
166
app/Services/AdminSettingsService.php
Normal file
166
app/Services/AdminSettingsService.php
Normal file
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Services\Internal\BeagleService;
|
||||
use App\User;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class AdminSettingsService
|
||||
{
|
||||
public static function getAll()
|
||||
{
|
||||
return [
|
||||
'features' => self::getFeatures(),
|
||||
'landing' => self::getLanding(),
|
||||
'branding' => self::getBranding(),
|
||||
'media' => self::getMedia(),
|
||||
'rules' => self::getRules(),
|
||||
'suggested_rules' => self::getSuggestedRules(),
|
||||
'users' => self::getUsers(),
|
||||
'posts' => self::getPosts(),
|
||||
'platform' => self::getPlatform(),
|
||||
'storage' => self::getStorage(),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getFeatures()
|
||||
{
|
||||
$cloud_storage = (bool) config_cache('pixelfed.cloud_storage');
|
||||
$cloud_disk = config('filesystems.cloud');
|
||||
$cloud_ready = ! empty(config('filesystems.disks.'.$cloud_disk.'.key')) && ! empty(config('filesystems.disks.'.$cloud_disk.'.secret'));
|
||||
$openReg = (bool) config_cache('pixelfed.open_registration');
|
||||
$curOnboarding = (bool) config_cache('instance.curated_registration.enabled');
|
||||
$regState = $openReg ? 'open' : ($curOnboarding ? 'filtered' : 'closed');
|
||||
|
||||
return [
|
||||
'registration_status' => $regState,
|
||||
'cloud_storage' => $cloud_ready && $cloud_storage,
|
||||
'activitypub_enabled' => (bool) config_cache('federation.activitypub.enabled'),
|
||||
'account_migration' => (bool) config_cache('federation.migration'),
|
||||
'mobile_apis' => (bool) config_cache('pixelfed.oauth_enabled'),
|
||||
'stories' => (bool) config_cache('instance.stories.enabled'),
|
||||
'instagram_import' => (bool) config_cache('pixelfed.import.instagram.enabled'),
|
||||
'autospam_enabled' => (bool) config_cache('pixelfed.bouncer.enabled'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getLanding()
|
||||
{
|
||||
$availableAdmins = User::whereIsAdmin(true)->get();
|
||||
$currentAdmin = config_cache('instance.admin.pid');
|
||||
|
||||
return [
|
||||
'admins' => $availableAdmins,
|
||||
'current_admin' => $currentAdmin,
|
||||
'show_directory' => (bool) config_cache('instance.landing.show_directory'),
|
||||
'show_explore' => (bool) config_cache('instance.landing.show_explore'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getBranding()
|
||||
{
|
||||
return [
|
||||
'name' => config_cache('app.name'),
|
||||
'short_description' => config_cache('app.short_description'),
|
||||
'long_description' => config_cache('app.description'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getMedia()
|
||||
{
|
||||
return [
|
||||
'max_photo_size' => config_cache('pixelfed.max_photo_size'),
|
||||
'max_album_length' => config_cache('pixelfed.max_album_length'),
|
||||
'image_quality' => config_cache('pixelfed.image_quality'),
|
||||
'media_types' => config_cache('pixelfed.media_types'),
|
||||
'optimize_image' => (bool) config_cache('pixelfed.optimize_image'),
|
||||
'optimize_video' => (bool) config_cache('pixelfed.optimize_video'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getRules()
|
||||
{
|
||||
return config_cache('app.rules') ? json_decode(config_cache('app.rules'), true) : [];
|
||||
}
|
||||
|
||||
public static function getSuggestedRules()
|
||||
{
|
||||
return BeagleService::getDefaultRules();
|
||||
}
|
||||
|
||||
public static function getUsers()
|
||||
{
|
||||
$autoFollow = config_cache('account.autofollow_usernames');
|
||||
if (strlen($autoFollow) >= 2) {
|
||||
$autoFollow = explode(',', $autoFollow);
|
||||
} else {
|
||||
$autoFollow = [];
|
||||
}
|
||||
|
||||
return [
|
||||
'require_email_verification' => (bool) config_cache('pixelfed.enforce_email_verification'),
|
||||
'enforce_account_limit' => (bool) config_cache('pixelfed.enforce_account_limit'),
|
||||
'max_account_size' => config_cache('pixelfed.max_account_size'),
|
||||
'admin_autofollow' => (bool) config_cache('account.autofollow'),
|
||||
'admin_autofollow_accounts' => $autoFollow,
|
||||
'max_user_blocks' => (int) config_cache('instance.user_filters.max_user_blocks'),
|
||||
'max_user_mutes' => (int) config_cache('instance.user_filters.max_user_mutes'),
|
||||
'max_domain_blocks' => (int) config_cache('instance.user_filters.max_domain_blocks'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPosts()
|
||||
{
|
||||
return [
|
||||
'max_caption_length' => config_cache('pixelfed.max_caption_length'),
|
||||
'max_altext_length' => config_cache('pixelfed.max_altext_length'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPlatform()
|
||||
{
|
||||
return [
|
||||
'allow_app_registration' => (bool) config_cache('pixelfed.allow_app_registration'),
|
||||
'app_registration_rate_limit_attempts' => config_cache('pixelfed.app_registration_rate_limit_attempts'),
|
||||
'app_registration_rate_limit_decay' => config_cache('pixelfed.app_registration_rate_limit_decay'),
|
||||
'app_registration_confirm_rate_limit_attempts' => config_cache('pixelfed.app_registration_confirm_rate_limit_attempts'),
|
||||
'app_registration_confirm_rate_limit_decay' => config_cache('pixelfed.app_registration_confirm_rate_limit_decay'),
|
||||
'allow_post_embeds' => (bool) config_cache('instance.embed.post'),
|
||||
'allow_profile_embeds' => (bool) config_cache('instance.embed.profile'),
|
||||
'captcha_enabled' => (bool) config_cache('captcha.enabled'),
|
||||
'captcha_on_login' => (bool) config_cache('captcha.active.login'),
|
||||
'captcha_on_register' => (bool) config_cache('captcha.active.register'),
|
||||
'captcha_secret' => Str::of(config_cache('captcha.secret'))->mask('*', 4, -4),
|
||||
'captcha_sitekey' => Str::of(config_cache('captcha.sitekey'))->mask('*', 4, -4),
|
||||
'custom_emoji_enabled' => (bool) config_cache('federation.custom_emoji.enabled'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getStorage()
|
||||
{
|
||||
$cloud_storage = (bool) config_cache('pixelfed.cloud_storage');
|
||||
$cloud_disk = config('filesystems.cloud');
|
||||
$cloud_ready = ! empty(config('filesystems.disks.'.$cloud_disk.'.key')) && ! empty(config('filesystems.disks.'.$cloud_disk.'.secret'));
|
||||
$primaryDisk = (bool) $cloud_ready && $cloud_storage;
|
||||
$pkey = 'filesystems.disks.'.$cloud_disk.'.';
|
||||
$disk = [
|
||||
'driver' => $cloud_disk,
|
||||
'key' => Str::of(config_cache($pkey.'key'))->mask('*', 0, -2),
|
||||
'secret' => Str::of(config_cache($pkey.'secret'))->mask('*', 0, -2),
|
||||
'region' => config_cache($pkey.'region'),
|
||||
'bucket' => config_cache($pkey.'bucket'),
|
||||
'visibility' => config_cache($pkey.'visibility'),
|
||||
'endpoint' => config_cache($pkey.'endpoint'),
|
||||
'url' => config_cache($pkey.'url'),
|
||||
'use_path_style_endpoint' => config_cache($pkey.'use_path_style_endpoint'),
|
||||
];
|
||||
|
||||
return [
|
||||
'primary_disk' => $primaryDisk ? 'cloud' : 'local',
|
||||
'cloud_ready' => (bool) $cloud_ready,
|
||||
'cloud_disk' => $cloud_disk,
|
||||
'disk_config' => $disk,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -2,22 +2,26 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Util\Lexer\Classifier;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Util\Lexer\Classifier;
|
||||
|
||||
class AutospamService
|
||||
{
|
||||
const CHCKD_CACHE_KEY = 'pf:services:autospam:nlp:checked';
|
||||
|
||||
const MODEL_CACHE_KEY = 'pf:services:autospam:nlp:model-cache';
|
||||
|
||||
const MODEL_FILE_PATH = 'nlp/active-training-data.json';
|
||||
|
||||
const MODEL_SPAM_PATH = 'nlp/spam.json';
|
||||
|
||||
const MODEL_HAM_PATH = 'nlp/ham.json';
|
||||
|
||||
public static function check($text)
|
||||
{
|
||||
if (! $text || strlen($text) == 0) {
|
||||
false;
|
||||
|
||||
}
|
||||
if (! self::active()) {
|
||||
return null;
|
||||
|
@ -25,13 +29,14 @@ class AutospamService
|
|||
$model = self::getCachedModel();
|
||||
$classifier = new Classifier;
|
||||
$classifier->import($model['documents'], $model['words']);
|
||||
|
||||
return $classifier->most($text) === 'spam';
|
||||
}
|
||||
|
||||
public static function eligible()
|
||||
{
|
||||
return Cache::remember(self::CHCKD_CACHE_KEY, 86400, function () {
|
||||
if(!config_cache('pixelfed.bouncer.enabled') || !config('autospam.enabled')) {
|
||||
if (! (bool) config_cache('pixelfed.bouncer.enabled') || ! (bool) config_cache('autospam.enabled')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,14 @@ use Cache;
|
|||
class ConfigCacheService
|
||||
{
|
||||
const CACHE_KEY = 'config_cache:_v0-key:';
|
||||
const PROTECTED_KEYS = [
|
||||
'filesystems.disks.s3.key',
|
||||
'filesystems.disks.s3.secret',
|
||||
'filesystems.disks.spaces.key',
|
||||
'filesystems.disks.spaces.secret',
|
||||
'captcha.secret',
|
||||
'captcha.sitekey',
|
||||
];
|
||||
|
||||
public static function get($key)
|
||||
{
|
||||
|
@ -89,6 +97,41 @@ class ConfigCacheService
|
|||
'pixelfed.app_registration_confirm_rate_limit_decay',
|
||||
'instance.embed.profile',
|
||||
'instance.embed.post',
|
||||
|
||||
'captcha.enabled',
|
||||
'captcha.secret',
|
||||
'captcha.sitekey',
|
||||
'captcha.active.login',
|
||||
'captcha.active.register',
|
||||
'captcha.triggers.login.enabled',
|
||||
'captcha.triggers.login.attempts',
|
||||
'federation.custom_emoji.enabled',
|
||||
|
||||
'pixelfed.optimize_image',
|
||||
'pixelfed.optimize_video',
|
||||
'pixelfed.max_collection_length',
|
||||
'media.delete_local_after_cloud',
|
||||
'instance.user_filters.max_user_blocks',
|
||||
'instance.user_filters.max_user_mutes',
|
||||
'instance.user_filters.max_domain_blocks',
|
||||
|
||||
'filesystems.disks.s3.key',
|
||||
'filesystems.disks.s3.secret',
|
||||
'filesystems.disks.s3.region',
|
||||
'filesystems.disks.s3.bucket',
|
||||
'filesystems.disks.s3.visibility',
|
||||
'filesystems.disks.s3.url',
|
||||
'filesystems.disks.s3.endpoint',
|
||||
'filesystems.disks.s3.use_path_style_endpoint',
|
||||
|
||||
'filesystems.disks.spaces.key',
|
||||
'filesystems.disks.spaces.secret',
|
||||
'filesystems.disks.spaces.region',
|
||||
'filesystems.disks.spaces.bucket',
|
||||
'filesystems.disks.spaces.visibility',
|
||||
'filesystems.disks.spaces.url',
|
||||
'filesystems.disks.spaces.endpoint',
|
||||
'filesystems.disks.spaces.use_path_style_endpoint',
|
||||
// 'system.user_mode'
|
||||
];
|
||||
|
||||
|
@ -100,20 +143,34 @@ class ConfigCacheService
|
|||
return config($key);
|
||||
}
|
||||
|
||||
$protect = false;
|
||||
$protected = null;
|
||||
if(in_array($key, self::PROTECTED_KEYS)) {
|
||||
$protect = true;
|
||||
}
|
||||
|
||||
$v = config($key);
|
||||
$c = ConfigCacheModel::where('k', $key)->first();
|
||||
|
||||
if ($c) {
|
||||
if($protect) {
|
||||
return decrypt($c->v) ?? config($key);
|
||||
} else {
|
||||
return $c->v ?? config($key);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $v) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($protect && $v) {
|
||||
$protected = encrypt($v);
|
||||
}
|
||||
|
||||
$cc = new ConfigCacheModel;
|
||||
$cc->k = $key;
|
||||
$cc->v = $v;
|
||||
$cc->v = $protect ? $protected : $v;
|
||||
$cc->save();
|
||||
|
||||
return $v;
|
||||
|
@ -124,8 +181,15 @@ class ConfigCacheService
|
|||
{
|
||||
$exists = ConfigCacheModel::whereK($key)->first();
|
||||
|
||||
$protect = false;
|
||||
$protected = null;
|
||||
if(in_array($key, self::PROTECTED_KEYS)) {
|
||||
$protect = true;
|
||||
$protected = encrypt($val);
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
$exists->v = $val;
|
||||
$exists->v = $protect ? $protected : $val;
|
||||
$exists->save();
|
||||
Cache::put(self::CACHE_KEY.$key, $val, now()->addHours(12));
|
||||
|
||||
|
@ -134,7 +198,7 @@ class ConfigCacheService
|
|||
|
||||
$cc = new ConfigCacheModel;
|
||||
$cc->k = $key;
|
||||
$cc->v = $val;
|
||||
$cc->v = $protect ? $protected : $val;
|
||||
$cc->save();
|
||||
|
||||
Cache::put(self::CACHE_KEY.$key, $val, now()->addHours(12));
|
||||
|
|
|
@ -13,7 +13,7 @@ class CustomEmojiService
|
|||
{
|
||||
public static function get($shortcode)
|
||||
{
|
||||
if(config('federation.custom_emoji.enabled') == false) {
|
||||
if((bool) config_cache('federation.custom_emoji.enabled') == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ class CustomEmojiService
|
|||
|
||||
public static function import($url, $id = false)
|
||||
{
|
||||
if(config('federation.custom_emoji.enabled') == false) {
|
||||
if((bool) config_cache('federation.custom_emoji.enabled') == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
82
app/Services/FilesystemService.php
Normal file
82
app/Services/FilesystemService.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Aws\S3\S3Client;
|
||||
use Aws\S3\Exception\S3Exception;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
|
||||
use League\Flysystem\Filesystem;
|
||||
use League\Flysystem\UnableToRetrieveMetadata;
|
||||
use League\Flysystem\FilesystemException;
|
||||
use League\Flysystem\UnableToListContents;
|
||||
use League\Flysystem\FileAttributes;
|
||||
use League\Flysystem\UnableToWriteFile;
|
||||
|
||||
class FilesystemService
|
||||
{
|
||||
const VERIFY_FILE_NAME = 'cfstest.txt';
|
||||
|
||||
public static function getVerifyCredentials($key, $secret, $region, $bucket, $endpoint)
|
||||
{
|
||||
$client = new S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => $region,
|
||||
'endpoint' => $endpoint,
|
||||
'credentials' => [
|
||||
'key' => $key,
|
||||
'secret' => $secret,
|
||||
]
|
||||
]);
|
||||
|
||||
$adapter = new AwsS3V3Adapter(
|
||||
$client,
|
||||
$bucket,
|
||||
);
|
||||
|
||||
$throw = false;
|
||||
$filesystem = new Filesystem($adapter);
|
||||
|
||||
$writable = false;
|
||||
try {
|
||||
$filesystem->write(self::VERIFY_FILE_NAME, 'ok', []);
|
||||
$writable = true;
|
||||
} catch (FilesystemException | UnableToWriteFile $exception) {
|
||||
$writable = false;
|
||||
}
|
||||
|
||||
if(!$writable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $filesystem->read(self::VERIFY_FILE_NAME);
|
||||
if($response === 'ok') {
|
||||
$writable = true;
|
||||
$res[] = self::VERIFY_FILE_NAME;
|
||||
} else {
|
||||
$writable = false;
|
||||
}
|
||||
} catch (FilesystemException | UnableToReadFile $exception) {
|
||||
$writable = false;
|
||||
}
|
||||
|
||||
if(in_array(self::VERIFY_FILE_NAME, $res)) {
|
||||
try {
|
||||
$filesystem->delete(self::VERIFY_FILE_NAME);
|
||||
} catch (FilesystemException | UnableToDeleteFile $exception) {
|
||||
$writable = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$writable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(in_array(self::VERIFY_FILE_NAME, $res)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
44
app/Services/Internal/BeagleService.php
Normal file
44
app/Services/Internal/BeagleService.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Internal;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Http\Client\ConnectionException;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
|
||||
class BeagleService
|
||||
{
|
||||
const DEFAULT_RULES_CACHE_KEY = 'pf:services:beagle:default_rules:v1';
|
||||
|
||||
public static function getDefaultRules()
|
||||
{
|
||||
return Cache::remember(self::DEFAULT_RULES_CACHE_KEY, now()->addDays(7), function() {
|
||||
try {
|
||||
$res = Http::withOptions(['allow_redirects' => false])
|
||||
->timeout(5)
|
||||
->connectTimeout(5)
|
||||
->retry(2, 500)
|
||||
->get('https://beagle.pixelfed.net/api/v1/common/suggestions/rules');
|
||||
} catch (RequestException $e) {
|
||||
return;
|
||||
} catch (ConnectionException $e) {
|
||||
return;
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$res->ok()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$json = $res->json();
|
||||
|
||||
if(!isset($json['rule_suggestions']) || !count($json['rule_suggestions'])) {
|
||||
return [];
|
||||
}
|
||||
return $json['rule_suggestions'];
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -53,8 +53,8 @@ class LandingService
|
|||
'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'),
|
||||
'show_directory' => (bool) config_cache('instance.landing.show_directory'),
|
||||
'show_explore_feed' => (bool) config_cache('instance.landing.show_explore'),
|
||||
'open_registration' => (bool) $openReg,
|
||||
'curated_onboarding' => (bool) config_cache('instance.curated_registration.enabled'),
|
||||
'version' => config('pixelfed.version'),
|
||||
|
@ -85,7 +85,7 @@ class LandingService
|
|||
'media_types' => config_cache('pixelfed.media_types'),
|
||||
],
|
||||
'features' => [
|
||||
'federation' => config_cache('federation.activitypub.enabled'),
|
||||
'federation' => (bool) config_cache('federation.activitypub.enabled'),
|
||||
'timelines' => [
|
||||
'local' => true,
|
||||
'network' => (bool) config_cache('federation.network_timeline'),
|
||||
|
|
|
@ -2,32 +2,26 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Jobs\AvatarPipeline\AvatarStorageCleanup;
|
||||
use App\Jobs\MediaPipeline\MediaDeletePipeline;
|
||||
use App\Media;
|
||||
use App\Util\ActivityPub\Helpers;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Illuminate\Http\File;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
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)
|
||||
{
|
||||
if(config_cache('pixelfed.cloud_storage') == true) {
|
||||
if ((bool) config_cache('pixelfed.cloud_storage') == true) {
|
||||
(new self())->cloudStore($media);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public static function move(Media $media)
|
||||
|
@ -36,10 +30,10 @@ class MediaStorageService {
|
|||
return;
|
||||
}
|
||||
|
||||
if(config_cache('pixelfed.cloud_storage') == true) {
|
||||
if ((bool) config_cache('pixelfed.cloud_storage') == true) {
|
||||
return (new self())->cloudMove($media);
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public static function avatar($avatar, $local = false, $skipRecentCheck = false)
|
||||
|
@ -73,7 +67,7 @@ class MediaStorageService {
|
|||
|
||||
return [
|
||||
'length' => $len,
|
||||
'mime' => $mime
|
||||
'mime' => $mime,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -132,7 +126,7 @@ class MediaStorageService {
|
|||
$mimes = [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'video/mp4'
|
||||
'video/mp4',
|
||||
];
|
||||
|
||||
$mime = $head['mime'];
|
||||
|
@ -258,6 +252,7 @@ class MediaStorageService {
|
|||
$avatar->last_fetched_at = now();
|
||||
$avatar->save();
|
||||
unlink($tmpName);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,49 +2,34 @@
|
|||
|
||||
namespace App\Util\ActivityPub;
|
||||
|
||||
use DB, Cache, Purify, Storage, Request, Validator;
|
||||
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\Instance;
|
||||
use App\Jobs\AvatarPipeline\RemoteAvatarFetch;
|
||||
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 Illuminate\Contracts\Cache\LockTimeoutException;
|
||||
use App\Services\DomainService;
|
||||
use App\Services\UserFilterService;
|
||||
use App\Profile;
|
||||
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)
|
||||
{
|
||||
$verbs = ['Create', 'Announce', 'Like', 'Follow', 'Delete', 'Accept', 'Reject', 'Undo', 'Tombstone'];
|
||||
|
@ -53,14 +38,14 @@ class Helpers {
|
|||
'type' => [
|
||||
'required',
|
||||
'string',
|
||||
Rule::in($verbs)
|
||||
Rule::in($verbs),
|
||||
],
|
||||
'id' => 'required|string',
|
||||
'actor' => 'required|string|url',
|
||||
'object' => 'required',
|
||||
'object.type' => 'required_if:type,Create',
|
||||
'object.attributedTo' => 'required_if:type,Create|url',
|
||||
'published' => 'required_if:type,Create|date'
|
||||
'published' => 'required_if:type,Create|date',
|
||||
])->passes();
|
||||
|
||||
return $valid;
|
||||
|
@ -100,13 +85,13 @@ class Helpers {
|
|||
'*.type' => [
|
||||
'required',
|
||||
'string',
|
||||
Rule::in($mediaTypes)
|
||||
Rule::in($mediaTypes),
|
||||
],
|
||||
'*.url' => 'required|url',
|
||||
'*.mediaType' => [
|
||||
'required',
|
||||
'string',
|
||||
Rule::in($mimeTypes)
|
||||
Rule::in($mimeTypes),
|
||||
],
|
||||
'*.name' => 'sometimes|nullable|string',
|
||||
'*.blurhash' => 'sometimes|nullable|string|min:6|max:164',
|
||||
|
@ -132,6 +117,7 @@ class Helpers {
|
|||
foreach ($data['to'] as $to) {
|
||||
if ($to == 'https://www.w3.org/ns/activitystreams#Public') {
|
||||
$scope = 'public';
|
||||
|
||||
continue;
|
||||
}
|
||||
$url = $localOnly ? self::validateLocalUrl($to) : self::validateUrl($to);
|
||||
|
@ -145,6 +131,7 @@ class Helpers {
|
|||
foreach ($data['cc'] as $cc) {
|
||||
if ($cc == 'https://www.w3.org/ns/activitystreams#Public') {
|
||||
$scope = 'unlisted';
|
||||
|
||||
continue;
|
||||
}
|
||||
$url = $localOnly ? self::validateLocalUrl($cc) : self::validateUrl($cc);
|
||||
|
@ -154,6 +141,7 @@ class Helpers {
|
|||
}
|
||||
}
|
||||
$audience['scope'] = $scope;
|
||||
|
||||
return $audience;
|
||||
}
|
||||
|
||||
|
@ -161,6 +149,7 @@ class Helpers {
|
|||
{
|
||||
$audience = self::normalizeAudience($data);
|
||||
$url = $profile->permalink();
|
||||
|
||||
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) {
|
||||
$localhosts = [
|
||||
'127.0.0.1', 'localhost', '::1'
|
||||
'127.0.0.1', 'localhost', '::1',
|
||||
];
|
||||
|
||||
if (strtolower(mb_substr($url, 0, 8)) !== 'https://') {
|
||||
|
@ -228,8 +217,10 @@ class Helpers {
|
|||
$domain = config('pixelfed.domain.app');
|
||||
$host = parse_url($url, PHP_URL_HOST);
|
||||
$url = strtolower($domain) === strtolower($host) ? $url : false;
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -237,6 +228,7 @@ class Helpers {
|
|||
{
|
||||
$version = config('pixelfed.version');
|
||||
$url = config('app.url');
|
||||
|
||||
return [
|
||||
'Accept' => 'application/activity+json',
|
||||
'User-Agent' => "(Pixelfed/{$version}; +{$url})",
|
||||
|
@ -297,6 +289,7 @@ class Helpers {
|
|||
|
||||
if ($local) {
|
||||
$id = (int) last(explode('/', $url));
|
||||
|
||||
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'])) {
|
||||
$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';
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +348,7 @@ class Helpers {
|
|||
if (is_array($res['cc']) && in_array('https://www.w3.org/ns/activitystreams#Public', $res['cc'])) {
|
||||
$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';
|
||||
}
|
||||
}
|
||||
|
@ -417,8 +410,7 @@ class Helpers {
|
|||
if (! self::validateUrl($attributedTo) ||
|
||||
$idDomain !== $actorDomain ||
|
||||
$actorDomain !== $urlDomain
|
||||
)
|
||||
{
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -466,6 +458,7 @@ class Helpers {
|
|||
$scope,
|
||||
$id
|
||||
);
|
||||
|
||||
return $status;
|
||||
} else {
|
||||
$status = self::storeStatus($url, $profile, $res);
|
||||
|
@ -512,7 +505,7 @@ class Helpers {
|
|||
|
||||
$status = Status::updateOrCreate(
|
||||
[
|
||||
'uri' => $url
|
||||
'uri' => $url,
|
||||
], [
|
||||
'profile_id' => $pid,
|
||||
'url' => $url,
|
||||
|
@ -527,7 +520,7 @@ class Helpers {
|
|||
'visibility' => $scope,
|
||||
'cw_summary' => ($cw == true && isset($activity['summary']) ?
|
||||
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'])) {
|
||||
$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';
|
||||
}
|
||||
}
|
||||
|
@ -629,7 +622,7 @@ class Helpers {
|
|||
if (is_array($activity['cc']) && in_array('https://www.w3.org/ns/activitystreams#Public', $activity['cc'])) {
|
||||
$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';
|
||||
}
|
||||
}
|
||||
|
@ -700,6 +693,7 @@ class Helpers {
|
|||
if (self::verifyAttachments($data) == false) {
|
||||
// \Log::info('importNoteAttachment::failedVerification.', [$data['id']]);
|
||||
$status->viewType();
|
||||
|
||||
return;
|
||||
}
|
||||
$attachments = isset($data['object']) ? $data['object']['attachment'] : $data['attachment'];
|
||||
|
@ -748,13 +742,13 @@ class Helpers {
|
|||
$media->version = 3;
|
||||
$media->save();
|
||||
|
||||
if(config_cache('pixelfed.cloud_storage') == true) {
|
||||
if ((bool) config_cache('pixelfed.cloud_storage') == true) {
|
||||
MediaStoragePipeline::dispatch($media);
|
||||
}
|
||||
}
|
||||
|
||||
$status->viewType();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public static function profileFirstOrNew($url)
|
||||
|
@ -769,6 +763,7 @@ class Helpers {
|
|||
|
||||
if ($local == true) {
|
||||
$id = last(explode('/', $url));
|
||||
|
||||
return Profile::whereNull('status')
|
||||
->whereNull('domain')
|
||||
->whereUsername($id)
|
||||
|
@ -779,6 +774,7 @@ class Helpers {
|
|||
if ($profile->last_fetched_at && $profile->last_fetched_at->lt(now()->subHours(24))) {
|
||||
return self::profileUpdateOrCreate($url);
|
||||
}
|
||||
|
||||
return $profile;
|
||||
}
|
||||
|
||||
|
@ -821,7 +817,7 @@ class Helpers {
|
|||
}
|
||||
|
||||
$instance = Instance::updateOrCreate([
|
||||
'domain' => $domain
|
||||
'domain' => $domain,
|
||||
]);
|
||||
if ($instance->wasRecentlyCreated == true) {
|
||||
\App\Jobs\InstancePipeline\FetchNodeinfoPipeline::dispatch($instance)->onQueue('low');
|
||||
|
@ -853,6 +849,7 @@ class Helpers {
|
|||
}
|
||||
$profile->last_fetched_at = now();
|
||||
$profile->save();
|
||||
|
||||
return $profile;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,18 +2,16 @@
|
|||
|
||||
namespace App\Util\ActivityPub;
|
||||
|
||||
use App\Profile;
|
||||
use App\Status;
|
||||
use League\Fractal;
|
||||
use App\Http\Controllers\ProfileController;
|
||||
use App\Transformer\ActivityPub\ProfileOutbox;
|
||||
use App\Status;
|
||||
use App\Transformer\ActivityPub\Verb\CreateNote;
|
||||
use League\Fractal;
|
||||
|
||||
class Outbox {
|
||||
|
||||
class Outbox
|
||||
{
|
||||
public static function get($profile)
|
||||
{
|
||||
abort_if(!config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
|
||||
abort_if(! config('federation.activitypub.outbox'), 404);
|
||||
|
||||
if ($profile->status != null) {
|
||||
|
@ -43,9 +41,9 @@ class Outbox {
|
|||
'id' => $profile->permalink('/outbox'),
|
||||
'type' => 'OrderedCollection',
|
||||
'totalItems' => $count,
|
||||
'orderedItems' => $res['data']
|
||||
'orderedItems' => $res['data'],
|
||||
];
|
||||
|
||||
return $outbox;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,16 +30,16 @@ class Config
|
|||
'version' => config('pixelfed.version'),
|
||||
'open_registration' => (bool) config_cache('pixelfed.open_registration'),
|
||||
'uploader' => [
|
||||
'max_photo_size' => (int) config('pixelfed.max_photo_size'),
|
||||
'max_photo_size' => (int) config_cache('pixelfed.max_photo_size'),
|
||||
'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),
|
||||
'max_collection_length' => (int) config_cache('pixelfed.max_collection_length', 18),
|
||||
|
||||
'optimize_image' => (bool) config('pixelfed.optimize_image'),
|
||||
'optimize_video' => (bool) config('pixelfed.optimize_video'),
|
||||
'optimize_image' => (bool) config_cache('pixelfed.optimize_image'),
|
||||
'optimize_video' => (bool) config_cache('pixelfed.optimize_video'),
|
||||
|
||||
'media_types' => config_cache('pixelfed.media_types'),
|
||||
'mime_types' => config_cache('pixelfed.media_types') ? explode(',', config_cache('pixelfed.media_types')) : [],
|
||||
|
|
|
@ -19,7 +19,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
ini_set('memory_limit', '-1');
|
||||
if(config_cache('pixelfed.cloud_storage') == false) {
|
||||
if((bool) config_cache('pixelfed.cloud_storage') == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
BIN
public/css/admin.css
vendored
BIN
public/css/admin.css
vendored
Binary file not shown.
BIN
public/css/spa.css
vendored
BIN
public/css/spa.css
vendored
Binary file not shown.
BIN
public/js/admin.js
vendored
BIN
public/js/admin.js
vendored
Binary file not shown.
BIN
public/js/manifest.js
vendored
BIN
public/js/manifest.js
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -202,16 +202,12 @@
|
|||
if(res.data && res.data.length) {
|
||||
this.feed = res.data;
|
||||
this.maxId = res.data[res.data.length - 1].id;
|
||||
return true;
|
||||
this.canLoadMore = true;
|
||||
} else {
|
||||
this.feedLoaded = true;
|
||||
this.isLoaded = true;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
this.canLoadMore = res;
|
||||
})
|
||||
.finally(() => {
|
||||
this.feedLoaded = true;
|
||||
this.isLoaded = true;
|
||||
|
@ -242,14 +238,11 @@
|
|||
if(res.data && res.data.length) {
|
||||
this.feed.push(...res.data);
|
||||
this.maxId = res.data[res.data.length - 1].id;
|
||||
return true;
|
||||
this.canLoadMore = true;
|
||||
} else {
|
||||
return false;
|
||||
this.canLoadMore = false;
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
this.canLoadMore = res;
|
||||
})
|
||||
.finally(() => {
|
||||
this.isIntersecting = false;
|
||||
})
|
||||
|
|
|
@ -251,10 +251,11 @@
|
|||
</div>
|
||||
<div>
|
||||
<b-button
|
||||
variant="secondary"
|
||||
@click="showInstanceModal = false"
|
||||
variant="link-dark"
|
||||
size="sm"
|
||||
@click="onViewMoreInstance"
|
||||
>
|
||||
Close
|
||||
View More
|
||||
</b-button>
|
||||
<b-button
|
||||
variant="primary"
|
||||
|
@ -885,8 +886,12 @@
|
|||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onViewMoreInstance() {
|
||||
this.showInstanceModal = false;
|
||||
window.location.href = '/i/admin/instances/show/' + this.instanceModal.id
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
1550
resources/assets/components/admin/AdminSettings.vue
Normal file
1550
resources/assets/components/admin/AdminSettings.vue
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="mb-0" :style="{ 'font-size':`${fontSize}px` }">{{ contentText }}</div>
|
||||
<p class="mb-0"><a v-if="canStepExpand || (canExpand && !expanded)" class="font-weight-bold small" href="#" @click="expand()">Read more</a></p>
|
||||
<p class="mb-0"><a v-if="canStepExpand || (canExpand && !expanded)" class="font-weight-bold small" href="#" @click.prevent="expand()">Read more</a></p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<div class="card shadow-none border card-body">
|
||||
<div class="form-group mb-0">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" :name="elementId" class="custom-control-input" :id="elementId" :checked="value" @change="$emit('change', !value)">
|
||||
<label class="custom-control-label font-weight-bold" :for="elementId">{{ name }}</label>
|
||||
</div>
|
||||
<p class="mt-1 mb-0 small text-muted" v-html="description"></p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
|
||||
value: {
|
||||
type: Boolean
|
||||
},
|
||||
|
||||
description: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
elementId: {
|
||||
get() {
|
||||
let name = this.name;
|
||||
name = name.toLowerCase();
|
||||
name = name.replace(/[^a-z0-9 -]/g, ' ');
|
||||
name = name.replace(/\s+/g, '-');
|
||||
name = name.replace(/^-+|-+$/g, '');
|
||||
return 'fec_' + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<div :class="[ isCard ? 'card shadow-none border card-body' : '' ]">
|
||||
<div
|
||||
class="form-group"
|
||||
:class="[ isInline ? 'd-flex align-items-center gap-1' : 'mb-1' ]">
|
||||
<label :for="elementId" class="font-weight-bold mb-0">{{ name }}</label>
|
||||
<input
|
||||
:id="elementId"
|
||||
class="form-control form-control-muted mb-0"
|
||||
:placeholder="placeholder"
|
||||
:value="value"
|
||||
@input="$emit('change', $event.target.value)"
|
||||
:disabled="isDisabled" />
|
||||
</div>
|
||||
<p v-if="description && description.length" class="help-text small text-muted mb-0" v-html="description">
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
|
||||
value: {
|
||||
type: String
|
||||
},
|
||||
|
||||
placeholder: {
|
||||
type: String
|
||||
},
|
||||
|
||||
description: {
|
||||
type: String
|
||||
},
|
||||
|
||||
isCard: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
isInline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
elementId: {
|
||||
get() {
|
||||
let name = this.name;
|
||||
name = name.toLowerCase();
|
||||
name = name.replace(/[^a-z0-9 -]/g, ' ');
|
||||
name = name.replace(/\s+/g, '-');
|
||||
name = name.replace(/^-+|-+$/g, '');
|
||||
return 'fec_' + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped="true">
|
||||
.gap-1 {
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,63 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div style="width:100px;"></div>
|
||||
<div>
|
||||
<h2 class="display-4 mb-0" style="font-weight: 800;">{{ title }}</h2>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-primary rounded-pill font-weight-bold px-5"
|
||||
:disabled="isSaving || saved"
|
||||
@click.prevent="save">
|
||||
<template v-if="isSaving === true"><b-spinner small class="mx-2" /></template>
|
||||
<template v-else>{{ buttonLabel }}</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mt-3">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String
|
||||
},
|
||||
saving: {
|
||||
type: Boolean
|
||||
},
|
||||
saved: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
buttonLabel: {
|
||||
get() {
|
||||
if(this.saved) {
|
||||
return 'Saved';
|
||||
}
|
||||
if(this.saving) {
|
||||
return 'Saving';
|
||||
}
|
||||
|
||||
return 'Save';
|
||||
}
|
||||
},
|
||||
isSaving: {
|
||||
get() {
|
||||
return this.saving;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
save($event) {
|
||||
$event.currentTarget?.blur();
|
||||
this.$emit('save');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
10
resources/assets/js/admin.js
vendored
10
resources/assets/js/admin.js
vendored
|
@ -36,11 +36,21 @@ Vue.component(
|
|||
require('./../components/admin/AdminReports.vue').default
|
||||
);
|
||||
|
||||
Vue.component(
|
||||
'admin-settings',
|
||||
require('./../components/admin/AdminSettings.vue').default
|
||||
);
|
||||
|
||||
Vue.component(
|
||||
'instances-component',
|
||||
require('./../components/admin/AdminInstances.vue').default
|
||||
);
|
||||
|
||||
// Vue.component(
|
||||
// 'instance-details-component',
|
||||
// require('./../components/admin/AdminInstanceDetails.vue').default
|
||||
// );
|
||||
|
||||
Vue.component(
|
||||
'hashtag-component',
|
||||
require('./../components/admin/AdminHashtags.vue').default
|
||||
|
|
1
resources/assets/sass/lib/nucleo.css
vendored
1
resources/assets/sass/lib/nucleo.css
vendored
|
@ -10,6 +10,7 @@ License - nucleoapp.com/license/
|
|||
src: url('/fonts/nucleo-icons.eot') format('embedded-opentype'), url('/fonts/nucleo-icons.woff2') format('woff2'), url('/fonts/nucleo-icons.woff') format('woff'), url('/fonts/nucleo-icons.ttf') format('truetype'), url('/fonts/nucleo-icons.svg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
/*------------------------
|
||||
base class definition
|
||||
|
|
4
resources/assets/sass/spa.scss
vendored
4
resources/assets/sass/spa.scss
vendored
|
@ -392,6 +392,10 @@ span.twitter-typeahead .tt-suggestion:focus {
|
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.timestamp-overlay-badge {
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
.timeline-status-component {
|
||||
.username {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config_cache('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config_cache('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config_cache('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-5">
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config_cache('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
</li>
|
||||
<li>
|
||||
<strong><span class="badge badge-primary">OAUTH</span> enabled: </strong>
|
||||
<span>{{ config_cache('pixelfed.oauth_enabled') ? '✅ true' : '❌ false' }}</span>
|
||||
<span>{{ (bool) config_cache('pixelfed.oauth_enabled') ? '✅ true' : '❌ false' }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<strong><span class="badge badge-primary">OAUTH</span> token_expiration</strong>
|
||||
|
@ -298,7 +298,7 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">FEDERATION</span></td>
|
||||
<td><strong>ACTIVITY_PUB</strong></td>
|
||||
<td><span>{{config_cache('federation.activitypub.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('federation.activitypub.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">FEDERATION</span></td>
|
||||
|
@ -358,7 +358,7 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">FEDERATION</span></td>
|
||||
<td><strong>PF_NETWORK_TIMELINE</strong></td>
|
||||
<td><span>{{config_cache('federation.network_timeline') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('federation.network_timeline') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">FEDERATION</span></td>
|
||||
|
@ -368,7 +368,7 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">FEDERATION</span></td>
|
||||
<td><strong>CUSTOM_EMOJI</strong></td>
|
||||
<td><span>{{config_cache('federation.custom_emoji.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('federation.custom_emoji.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">FEDERATION</span></td>
|
||||
|
@ -545,7 +545,7 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">INSTANCE</span></td>
|
||||
<td><strong>STORIES_ENABLED</strong></td>
|
||||
<td><span>{{config_cache('instance.stories.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('instance.stories.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">INSTANCE</span></td>
|
||||
|
@ -740,7 +740,7 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></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>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
|
@ -750,12 +750,12 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
<td><strong>PF_OPTIMIZE_IMAGES</strong></td>
|
||||
<td><span>{{config_cache('pixelfed.optimize_image') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('pixelfed.optimize_image') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
<td><strong>PF_OPTIMIZE_VIDEOS</strong></td>
|
||||
<td><span>{{config_cache('pixelfed.optimize_video') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('pixelfed.optimize_video') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
|
@ -810,12 +810,12 @@
|
|||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
<td><strong>OAUTH_ENABLED</strong></td>
|
||||
<td><span>{{config_cache('pixelfed.oauth_enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{ (bool) config_cache('pixelfed.oauth_enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
<td><strong>PF_BOUNCER_ENABLED</strong></td>
|
||||
<td><span>{{config_cache('pixelfed.bouncer.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
<td><span>{{(bool) config_cache('pixelfed.bouncer.enabled') ? '✅ true' : '❌ false' }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="badge badge-primary">PIXELFED</span></td>
|
||||
|
|
|
@ -1,421 +1,12 @@
|
|||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="title mb-4">
|
||||
<h3 class="font-weight-bold">Settings</h3>
|
||||
@if(config('instance.enable_cc'))
|
||||
<p class="lead mb-0">Manage instance settings</p>
|
||||
</div>
|
||||
<form method="post">
|
||||
@csrf
|
||||
<ul class="nav nav-tabs nav-fill border-bottom-0" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-bold active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true"><i class="fas fa-home"></i></a>
|
||||
</li>
|
||||
<li class="nav-item border-none">
|
||||
<a class="nav-link font-weight-bold px-4" id="landing-tab" data-toggle="tab" href="#landing" role="tab" aria-controls="landing">Landing</a>
|
||||
</li>
|
||||
<li class="nav-item border-none">
|
||||
<a class="nav-link font-weight-bold px-4" id="brand-tab" data-toggle="tab" href="#brand" role="tab" aria-controls="brand">Brand</a>
|
||||
</li>
|
||||
{{-- <li class="nav-item border-none">
|
||||
<a class="nav-link font-weight-bold px-4" id="media-tab" data-toggle="tab" href="#media" role="tab" aria-controls="media">Mail</a>
|
||||
</li> --}}
|
||||
<li class="nav-item border-none">
|
||||
<a class="nav-link font-weight-bold px-4" id="media-tab" data-toggle="tab" href="#media" role="tab" aria-controls="media">Media</a>
|
||||
</li>
|
||||
<li class="nav-item border-none">
|
||||
<a class="nav-link font-weight-bold px-4" id="rules-tab" data-toggle="tab" href="#rules" role="tab" aria-controls="rules">Rules</a>
|
||||
</li>
|
||||
<li class="nav-item border-none">
|
||||
<a class="nav-link font-weight-bold px-4" id="users-tab" data-toggle="tab" href="#users" role="tab" aria-controls="users">Users</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-bold px-4" id="advanced-tab" data-toggle="tab" href="#advanced" role="tab" aria-controls="advanced">Advanced</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
|
||||
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
||||
{{-- <div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">System Configuration</label>
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span class="text-muted">Max Upload Size: </span>
|
||||
<span class="font-weight-bold">{{$system['max_upload_size']}}</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text-muted">Image Driver: </span>
|
||||
<span class="font-weight-bold">{{$system['image_driver']}}</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text-muted">Image Driver Loaded: </span>
|
||||
<span class="font-weight-bold">
|
||||
@if($system['image_driver_loaded'])
|
||||
<i class="fas fa-check text-success"></i>
|
||||
@else
|
||||
<i class="fas fa-times text-danger"></i>
|
||||
@endif
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text-muted">File Permissions: </span>
|
||||
<span class="font-weight-bold">
|
||||
@if($system['permissions'])
|
||||
<i class="fas fa-check text-success"></i>
|
||||
@else
|
||||
<i class="fas fa-times text-danger"></i>
|
||||
@endif
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text-muted"></span>
|
||||
<span class="font-weight-bold"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div> --}}
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">Features</label>
|
||||
|
||||
<div class="form-group row mb-5">
|
||||
<label for="staticEmail" class="col-sm-12 col-form-label font-weight-bold">Registration Status</label>
|
||||
<div class="col-sm-4">
|
||||
<select class="custom-select" name="regs">
|
||||
<option value="open" {{ $regState === 'open' ? 'selected' : '' }}>Open - Anyone can register</option>
|
||||
<option value="filtered" {{ $regState === 'filtered' ? 'selected' : '' }}>Filtered - Anyone can apply (Curated Onboarding)</option>
|
||||
<option value="closed" {{ $regState === 'closed' ? 'selected' : '' }}>Closed - Nobody can register</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($cloud_ready)
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="cloud_storage" class="custom-control-input" id="cls1" {{config_cache('pixelfed.cloud_storage') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="cls1">Cloud Storage</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Store photos & videos on S3 compatible object storage providers.</p>
|
||||
@endif
|
||||
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="activitypub" class="custom-control-input" id="ap" {{config_cache('federation.activitypub.enabled') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="ap">ActivityPub</label>
|
||||
</div>
|
||||
<p class="mb-4 small">ActivityPub federation, compatible with Pixelfed, Mastodon and other projects.</p>
|
||||
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="account_migration" class="custom-control-input" id="ap_mig" {{(bool)config_cache('federation.migration') ? 'checked' : ''}} {{(bool) config_cache('federation.activitypub.enabled') ? '' : 'disabled="disabled"'}}>
|
||||
<label class="custom-control-label font-weight-bold" for="ap_mig">Account Migration</label>
|
||||
</div>
|
||||
@if((bool) config_cache('federation.activitypub.enabled'))
|
||||
<p class="mb-4 small">Allow local accounts to migrate to other local or remote accounts.</p>
|
||||
@else
|
||||
<p class="mb-4 small text-muted"><strong>ActivityPub Required</strong> Allow local accounts to migrate to other local or remote accounts.</p>
|
||||
@endif
|
||||
|
||||
{{-- <div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="open_registration" class="custom-control-input" id="openReg" {{config_cache('pixelfed.open_registration') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="openReg">Open Registrations</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Allow new user registrations.</p> --}}
|
||||
|
||||
|
||||
{{-- <div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="registration_approvals" class="custom-control-input" id="openRegApproval" {{config_cache('pixelfed.registration_approvals') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="openRegApproval">Registration Approval Mode</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Manually review new account registration applications.</p> --}}
|
||||
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="mobile_apis" class="custom-control-input" id="cf2" {{config_cache('pixelfed.oauth_enabled') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="cf2">Mobile APIs</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Enable apis required for mobile app support.</p>
|
||||
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="stories" class="custom-control-input" id="cf3" {{config_cache('instance.stories.enabled') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="cf3">Stories</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Allow users to share ephemeral Stories.</p>
|
||||
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="ig_import" class="custom-control-input" id="cf4" {{config_cache('pixelfed.import.instagram.enabled') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="cf4">Instagram Import</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Allow <span class="font-weight-bold">experimental</span> Instagram Import support.</p>
|
||||
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="spam_detection" class="custom-control-input" id="cf5" {{config_cache('pixelfed.bouncer.enabled') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="cf5">Spam detection</label>
|
||||
</div>
|
||||
<p class="mb-4 small">Detect and remove spam from timelines.</p>
|
||||
</div>
|
||||
</div>
|
||||
{{-- <div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">Name</label>
|
||||
<input class="form-control col-8" name="name" placeholder="Pixelfed" value="{{config_cache('app.name')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">The instance name used in titles, metadata and apis.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-bottom">
|
||||
<label class="font-weight-bold text-muted">Short Description</label>
|
||||
<textarea class="form-control" rows="3" name="short_description">{{config_cache('app.short_description')}}</textarea>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Short description of instance used on various pages and apis.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-bottom">
|
||||
<label class="font-weight-bold text-muted">Long Description</label>
|
||||
<textarea class="form-control" rows="3" name="long_description">{{config_cache('app.description')}}</textarea>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Longer description of instance used on about page.</p>
|
||||
</div>
|
||||
</div> --}}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="landing" role="tabpanel" aria-labelledby="landing-tab">
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<p class="mb-0 small">Configure your landing page</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-bottom">
|
||||
<p class="font-weight-bold text-muted">Discovery</p>
|
||||
|
||||
<div class="my-3">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="show_directory" name="show_directory" {{ config_cache('instance.landing.show_directory') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="show_directory">Show Directory</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="show_explore_feed" name="show_explore_feed" {{ config_cache('instance.landing.show_explore') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="show_explore_feed">Show Explore Feed</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-bottom">
|
||||
<p class="font-weight-bold text-muted">Admin Account</p>
|
||||
|
||||
<div class="my-3">
|
||||
<select class="custom-select" name="admin_account_id" style="max-width: 300px;">
|
||||
<option selected disabled>Select an admin account</option>
|
||||
@foreach($availableAdmins as $acct)
|
||||
<option
|
||||
value="{{ $acct->profile_id }}" {!! $currentAdmin && $currentAdmin['id'] == $acct->profile_id ? 'selected' : null !!}
|
||||
>
|
||||
<span class="font-weight-bold">@{{ $acct->username }}</span>
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="brand" role="tabpanel" aria-labelledby="brand-tab">
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">Name</label>
|
||||
<input class="form-control col-8" name="name" placeholder="Pixelfed" value="{{config_cache('app.name')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">The instance name used in titles, metadata and apis.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-bottom">
|
||||
<label class="font-weight-bold text-muted">Short Description</label>
|
||||
<textarea class="form-control" rows="3" name="short_description">{{config_cache('app.short_description')}}</textarea>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Short description of instance used on various pages and apis.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-bottom">
|
||||
<label class="font-weight-bold text-muted">Long Description</label>
|
||||
<textarea class="form-control" rows="3" name="long_description">{{config_cache('app.description')}}</textarea>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Longer description of instance used on about page.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">About Title</label>
|
||||
<input class="form-control col-8" name="about_title" placeholder="Photo Sharing. For Everyone" value="{{config_cache('about.title')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">The header title used on the <a href="/site/about">about page</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="users" role="tabpanel" aria-labelledby="users-tab">
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top">
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="require_email_verification" class="custom-control-input" id="mailVerification" {{config_cache('pixelfed.enforce_email_verification') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="mailVerification">Require Email Verification</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top">
|
||||
<div class="custom-control custom-checkbox my-2">
|
||||
<input type="checkbox" name="enforce_account_limit" class="custom-control-input" id="userEnforceLimit" {{config_cache('pixelfed.enforce_account_limit') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="userEnforceLimit">Enable account storage limit</label>
|
||||
<p class="help-text small text-muted">Set a storage limit per user account.</p>
|
||||
</div>
|
||||
<label class="font-weight-bold text-muted">Account Limit</label>
|
||||
<input class="form-control" name="account_limit" placeholder="Pixelfed" value="{{config_cache('pixelfed.max_account_size')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">Account limit size in KB.</p>
|
||||
<p class="help-text small text-muted mb-0">{{config_cache('pixelfed.max_account_size')}} KB = {{floor(config_cache('pixelfed.max_account_size') / 1024)}} MB</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top">
|
||||
<div class="custom-control custom-checkbox my-2">
|
||||
<input type="checkbox" name="account_autofollow" class="custom-control-input" id="userAccountAutofollow" {{config_cache('account.autofollow') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="userAccountAutofollow">Auto Follow Accounts</label>
|
||||
<p class="help-text small text-muted">Enable auto follow accounts, new accounts will follow accounts you set.</p>
|
||||
</div>
|
||||
<label class="font-weight-bold text-muted">Accounts</label>
|
||||
<textarea class="form-control" name="account_autofollow_usernames" placeholder="Add account usernames to follow separated by commas">{{config_cache('account.autofollow_usernames')}}</textarea>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Add account usernames to follow separated by commas.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="media" role="tabpanel" aria-labelledby="media-tab">
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top">
|
||||
<label class="font-weight-bold text-muted">Max Size</label>
|
||||
<input class="form-control" name="max_photo_size" value="{{config_cache('pixelfed.max_photo_size')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">Maximum file upload size in KB</p>
|
||||
<p class="help-text small text-muted mb-0">{{config_cache('pixelfed.max_photo_size')}} KB = {{number_format(config_cache('pixelfed.max_photo_size') / 1024)}} MB</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top">
|
||||
<label class="font-weight-bold text-muted">Photo Album Limit</label>
|
||||
<input class="form-control" name="max_album_length" value="{{config_cache('pixelfed.max_album_length')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">The maximum number of photos or videos per album</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top">
|
||||
<label class="font-weight-bold text-muted">Image Quality</label>
|
||||
<input class="form-control" name="image_quality" value="{{config_cache('pixelfed.image_quality')}}">
|
||||
<p class="help-text small text-muted mt-3 mb-0">Image optimization quality from 0-100%. Set to 0 to disable image optimization.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">Media Types</label>
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="type_jpeg" class="custom-control-input" id="mediaType1" {{$jpeg ? 'checked' : ''}}>
|
||||
<label class="custom-control-label" for="mediaType1"><span class="border border-dark px-1 rounded font-weight-bold">JPEG</span></label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="type_png" class="custom-control-input" id="mediaType2" {{$png ? 'checked' : ''}}>
|
||||
<label class="custom-control-label" for="mediaType2"><span class="border border-dark px-1 rounded font-weight-bold">PNG</span></label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="type_gif" class="custom-control-input" id="mediaType3" {{$gif ? 'checked' : ''}}>
|
||||
<label class="custom-control-label" for="mediaType3"><span class="border border-dark px-1 rounded font-weight-bold">GIF</span></label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="type_webp" class="custom-control-input" id="mediaType4" {{$webp ? 'checked' : ''}}>
|
||||
<label class="custom-control-label" for="mediaType4"><span class="border border-dark px-1 rounded font-weight-bold">WebP</span></label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox mt-2">
|
||||
<input type="checkbox" name="type_mp4" class="custom-control-input" id="mediaType5" {{$mp4 ? 'checked' : ''}}>
|
||||
<label class="custom-control-label" for="mediaType5"><span class="border border-dark px-1 rounded font-weight-bold">MP4</span></label>
|
||||
</div>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Allowed media types.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="rules" role="tabpanel" aria-labelledby="rules-tab">
|
||||
<div class="border-top">
|
||||
<p class="lead mt-3 py-3 text-center">Add rules that explain what is acceptable use.</p>
|
||||
</div>
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<p class="font-weight-bold text-muted">Active Rules</p>
|
||||
<ol class="font-weight-bold">
|
||||
@if($rules)
|
||||
@foreach($rules as $rule)
|
||||
<li class="mb-4">
|
||||
<p class="mb-0">
|
||||
{{$rule}}
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm py-0 rule-delete" data-index="{{$loop->index}}">Delete</button>
|
||||
</p>
|
||||
</li>
|
||||
@endforeach
|
||||
@endif
|
||||
</ol>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">Add Rule</label>
|
||||
<input class="form-control" name="new_rule" placeholder="Add a new rule, we recommend being descriptive but keeping it short"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="advanced" role="tabpanel" aria-labelledby="advanced-tab">
|
||||
<div class="form-group mb-0">
|
||||
<div class="ml-n4 mr-n2 p-3 border-top border-bottom">
|
||||
<label class="font-weight-bold text-muted">Custom CSS</label>
|
||||
<div class="custom-control custom-checkbox my-2">
|
||||
<input type="checkbox" name="show_custom_css" class="custom-control-input" id="showCustomCss" {{config_cache('uikit.show_custom.css') ? 'checked' : ''}}>
|
||||
<label class="custom-control-label font-weight-bold" for="showCustomCss">Enable custom CSS</label>
|
||||
</div>
|
||||
<textarea class="form-control" name="custom_css" rows="3">{{config_cache('uikit.custom.css')}}</textarea>
|
||||
<p class="help-text small text-muted mt-3 mb-0">Add custom CSS, will be used on all pages</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group row mb-0 mt-4">
|
||||
<div class="col-12 text-right">
|
||||
<button type="submit" class="btn btn-primary font-weight-bold px-5">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@else
|
||||
</div>
|
||||
<div class="py-5">
|
||||
<p class="lead text-center font-weight-bold">Not enabled</p>
|
||||
<p class="text-center">Add <code>ENABLE_CONFIG_CACHE=true</code> in your <span class="font-weight-bold">.env</span> file <br /> and run <span class="font-weight-bold">php artisan config:cache</span></p>
|
||||
</div>
|
||||
@endif
|
||||
<admin-settings />
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
$('.rule-delete').on('click', function(e) {
|
||||
if(window.confirm('Are you sure you want to delete this rule?')) {
|
||||
let idx = e.target.dataset.index;
|
||||
axios.post(window.location.href, {
|
||||
'rule_delete': idx
|
||||
}).then(res => {
|
||||
$('.rule-delete[data-index="'+idx+'"]').parents().eq(1).remove();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
setTimeout(() => {
|
||||
$('.alert-success').fadeOut();
|
||||
}, 1000);
|
||||
});
|
||||
new Vue({ el: '#panel'});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if(config('captcha.enabled') || config('captcha.active.login') || config('captcha.active.register'))
|
||||
@if((bool) config_cache('captcha.enabled'))
|
||||
<label class="font-weight-bold small text-muted">Captcha</label>
|
||||
<div class="d-flex flex-grow-1">
|
||||
{!! Captcha::display(['data-theme' => 'dark']) !!}
|
||||
|
|
|
@ -76,10 +76,10 @@
|
|||
</div>
|
||||
|
||||
@if(
|
||||
config('captcha.enabled') ||
|
||||
config('captcha.active.login') ||
|
||||
(bool) config_cache('captcha.enabled') &&
|
||||
(bool) config_cache('captcha.active.login') ||
|
||||
(
|
||||
config('captcha.triggers.login.enabled') &&
|
||||
(bool) config_cache('captcha.triggers.login.enabled') &&
|
||||
request()->session()->has('login_attempts') &&
|
||||
request()->session()->get('login_attempts') >= config('captcha.triggers.login.attempts')
|
||||
)
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if(config('captcha.enabled'))
|
||||
@if((bool) config_cache('captcha.enabled'))
|
||||
<label class="font-weight-bold small text-muted">Captcha</label>
|
||||
<div class="d-flex flex-grow-1">
|
||||
{!! Captcha::display(['data-theme' => 'dark']) !!}
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if(config('captcha.enabled'))
|
||||
@if((bool) config_cache('captcha.enabled'))
|
||||
<label class="font-weight-bold small pt-3 text-muted">Captcha</label>
|
||||
<div class="d-flex flex-grow-1">
|
||||
{!! Captcha::display(['data-theme' => 'dark']) !!}
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if(config('captcha.enabled') || config('captcha.active.register'))
|
||||
@if((bool) config_cache('captcha.enabled') && (bool) config_cache('captcha.active.register'))
|
||||
<div class="d-flex justify-content-center my-3">
|
||||
{!! Captcha::display() !!}
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@extends('layouts.app',['title' => 'Welcome to ' . config('app.name')])
|
||||
@extends('layouts.app',['title' => 'Welcome to ' . config_cache('app.name')])
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
|
@ -14,7 +14,7 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
<p class="lead mb-0">Welcome to {{config('app.name')}}!</p>
|
||||
<p class="lead mb-0">Welcome to {{config_cache('app.name')}}!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<title>{{ $title ?? config('app.name', 'Pixelfed') }}</title>
|
||||
<title>{{ $title ?? config_cache('app.name', 'Pixelfed') }}</title>
|
||||
<link rel="manifest" href="{{url('/manifest.json')}}">
|
||||
|
||||
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:site_name" content="{{ config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:url" content="{{url(request()->url())}}">
|
||||
@stack('meta')
|
||||
|
|
|
@ -70,11 +70,11 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<title>{{ $title ?? config('app.name', 'Pixelfed') }}</title>
|
||||
<title>{{ $title ?? config_cache('app.name', 'Pixelfed') }}</title>
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
|
||||
<meta property="og:site_name" content="Pixelfed">
|
||||
<meta property="og:title" content="{{ $ogTitle ?? $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $ogTitle ?? $title ?? config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:type" content="{{ $ogType ?? 'article' }}">
|
||||
<meta property="og:url" content="{{url(request()->url())}}">
|
||||
@stack('meta')
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
<title>{{ $title ?? config_cache('app.name') }}</title>
|
||||
|
||||
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:site_name" content="{{ config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:url" content="{{request()->url()}}">
|
||||
@stack('meta')
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<title>{{ $title ?? config('app.name', 'Laravel') }}</title>
|
||||
<title>{{ $title ?? config_cache('app.name', 'Pixelfed') }}</title>
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
|
||||
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:site_name" content="{{ config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:url" content="{{request()->url()}}">
|
||||
@stack('meta')
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
{{__('navmenu.discover')}}
|
||||
</a>
|
||||
|
||||
@if(config_cache('instance.stories.enabled'))
|
||||
@if((bool) config_cache('instance.stories.enabled'))
|
||||
<a class="dropdown-item lead" href="/i/stories/new">
|
||||
<span style="width: 50px;margin-right:14px;">
|
||||
<span class="fal fa-history text-lighter fa-lg"></span>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="container">
|
||||
<a class="navbar-brand d-flex align-items-center" href="{{ url('/') }}">
|
||||
<img src="/img/pixelfed-icon-color.svg" height="30px" class="px-2" alt="Pixelfed logo">
|
||||
<span class="font-weight-bold mb-0" style="font-size:20px;">{{ config('app.name', 'Laravel') }}</span>
|
||||
<span class="font-weight-bold mb-0" style="font-size:20px;">{{ config_cache('app.name', 'Pixelfed') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
<title>{!! $title ?? config_cache('app.name') !!}</title>
|
||||
|
||||
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:site_name" content="{{ config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config_cache('app.name', 'pixelfed') }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:url" content="{{request()->url()}}">
|
||||
@stack('meta')
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue