Merge pull request #4309 from pixelfed/staging

Add php 8.2 support. Bump laravel version, v9 => v10
This commit is contained in:
daniel 2023-04-19 23:11:39 -06:00 committed by GitHub
commit ddc7b82683
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 583 additions and 731 deletions

View file

@ -7,7 +7,7 @@ jobs:
build: build:
docker: docker:
# Specify the version you desire here # Specify the version you desire here
- image: cimg/php:8.1.12 - image: cimg/php:8.2.5
# Specify service dependencies here if necessary # Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images # CircleCI maintains a library of pre-built images
@ -29,14 +29,14 @@ jobs:
- restore_cache: - restore_cache:
keys: keys:
# "composer.lock" can be used if it is committed to the repo # "composer.lock" can be used if it is committed to the repo
- v1-dependencies-{{ checksum "composer.json" }} - v2-dependencies-{{ checksum "composer.json" }}
# fallback to using the latest cache if no exact match is found # fallback to using the latest cache if no exact match is found
- v1-dependencies- - v2-dependencies-
- run: composer install -n --prefer-dist - run: composer install -n --prefer-dist
- save_cache: - save_cache:
key: composer-v1-{{ checksum "composer.lock" }} key: composer-v2-{{ checksum "composer.lock" }}
paths: paths:
- vendor - vendor

View file

@ -3,6 +3,7 @@
## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.5...dev) ## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.5...dev)
### Added ### Added
- Add php 8.2 support. Bump laravel version, v9 => v10 ([fb4ac4eb](https://github.com/pixelfed/pixelfed/commit/fb4ac4eb))
- New media:fix-nonlocal-driver command. Fixes s3 media created with invalid FILESYSTEM_DRIVER=s3 configuration ([672cccd4](https://github.com/pixelfed/pixelfed/commit/672cccd4)) - New media:fix-nonlocal-driver command. Fixes s3 media created with invalid FILESYSTEM_DRIVER=s3 configuration ([672cccd4](https://github.com/pixelfed/pixelfed/commit/672cccd4))
- New landing page design ([09c0032b](https://github.com/pixelfed/pixelfed/commit/09c0032b)) - New landing page design ([09c0032b](https://github.com/pixelfed/pixelfed/commit/09c0032b))

View file

@ -11,7 +11,10 @@ class AccountInterstitial extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['read_at', 'appeal_requested_at']; protected $casts = [
'read_at' => 'datetime',
'appeal_requested_at' => 'datetime'
];
public const JSON_MESSAGE = 'Please use web browser to proceed.'; public const JSON_MESSAGE = 'Please use web browser to proceed.';

View file

@ -6,7 +6,10 @@ use Illuminate\Database\Eloquent\Model;
class Activity extends Model class Activity extends Model
{ {
protected $dates = ['processed_at']; protected $casts = [
'processed_at' => 'datetime'
];
protected $fillable = ['data', 'to_id', 'from_id', 'object_type']; protected $fillable = ['data', 'to_id', 'from_id', 'object_type'];
public function toProfile() public function toProfile()

View file

@ -14,10 +14,10 @@ class Avatar extends Model
* *
* @var array * @var array
*/ */
protected $dates = [ protected $casts = [
'deleted_at', 'deleted_at' => 'datetime',
'last_fetched_at', 'last_fetched_at' => 'datetime',
'last_processed_at' 'last_processed_at' => 'datetime'
]; ];
protected $guarded = []; protected $guarded = [];

View file

@ -46,7 +46,7 @@ class VideoThumbnail extends Command
->take($limit) ->take($limit)
->get(); ->get();
foreach($videos as $video) { foreach($videos as $video) {
Pipeline::dispatchNow($video); Pipeline::dispatchSync($video);
} }
} }
} }

View file

@ -282,14 +282,22 @@ class AccountController extends Controller
$filterable['id'] = $profile->id; $filterable['id'] = $profile->id;
$filterable['type'] = $class; $filterable['type'] = $class;
Follower::whereProfileId($profile->id)->whereFollowingId($pid)->delete(); $followed = Follower::whereProfileId($profile->id)->whereFollowingId($pid)->first();
if($followed) {
$followed->delete();
$selfProfile = $request->user()->profile;
$selfProfile->followers_count = Follower::whereFollowingId($pid)->count();
$selfProfile->save();
AccountService::del($selfProfile->id);
}
Notification::whereProfileId($pid) Notification::whereProfileId($pid)
->whereActorId($profile->id) ->whereActorId($profile->id)
->get() ->get()
->map(function($n) use($pid) { ->map(function($n) use($pid) {
NotificationService::del($pid, $n['id']); NotificationService::del($pid, $n['id']);
$n->forceDelete(); $n->forceDelete();
}); });
break; break;
} }

View file

@ -46,7 +46,7 @@ class ContactController extends Controller
$contact->response = ''; $contact->response = '';
$contact->save(); $contact->save();
ContactPipeline::dispatchNow($contact); ContactPipeline::dispatchSync($contact);
return redirect()->back()->with('status', 'Success - Your message has been sent to admins.'); return redirect()->back()->with('status', 'Success - Your message has been sent to admins.');
} }

View file

@ -80,7 +80,7 @@ class DeleteAccountPipeline implements ShouldQueue
$id = $user->profile_id; $id = $user->profile_id;
Status::whereProfileId($id)->chunk(50, function($statuses) { Status::whereProfileId($id)->chunk(50, function($statuses) {
foreach($statuses as $status) { foreach($statuses as $status) {
StatusDelete::dispatchNow($status); StatusDelete::dispatchSync($status);
} }
}); });

View file

@ -95,7 +95,7 @@ class StatusDelete implements ShouldQueue
Media::whereStatusId($status->id) Media::whereStatusId($status->id)
->get() ->get()
->each(function($media) { ->each(function($media) {
MediaDeletePipeline::dispatchNow($media); MediaDeletePipeline::dispatchSync($media);
}); });
if($status->in_reply_to_id) { if($status->in_reply_to_id) {

View file

@ -16,7 +16,10 @@ class Like extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['deleted_at']; protected $casts = [
'deleted_at' => 'datetime'
];
protected $fillable = ['profile_id', 'status_id', 'status_profile_id']; protected $fillable = ['profile_id', 'status_id', 'status_profile_id'];
public function actor() public function actor()

View file

@ -17,12 +17,11 @@ class Media extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['deleted_at'];
protected $guarded = []; protected $guarded = [];
protected $casts = [ protected $casts = [
'srcset' => 'array' 'srcset' => 'array',
'deleted_at' => 'datetime'
]; ];
public function status() public function status()

View file

@ -14,7 +14,9 @@ class Mention extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['deleted_at']; protected $casts = [
'deleted_at' => 'datetime'
];
protected $guarded = []; protected $guarded = [];

View file

@ -9,7 +9,9 @@ class Newsroom extends Model
protected $table = 'newsroom'; protected $table = 'newsroom';
protected $fillable = ['title']; protected $fillable = ['title'];
protected $dates = ['published_at']; protected $casts = [
'published_at' => 'datetime'
];
public function permalink() public function permalink()
{ {

View file

@ -14,7 +14,9 @@ class Notification extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['deleted_at']; protected $casts = [
'deleted_at' => 'datetime'
];
protected $guarded = []; protected $guarded = [];

View file

@ -19,10 +19,10 @@ class Profile extends Model
*/ */
public $incrementing = false; public $incrementing = false;
protected $dates = [ protected $casts = [
'deleted_at', 'deleted_at' => 'datetime',
'last_fetched_at', 'last_fetched_at' => 'datetime',
'last_status_at' 'last_status_at' => 'datetime'
]; ];
protected $hidden = ['private_key']; protected $hidden = ['private_key'];
protected $visible = ['id', 'user_id', 'username', 'name']; protected $visible = ['id', 'user_id', 'username', 'name'];

View file

@ -24,10 +24,7 @@ class AuthServiceProvider extends ServiceProvider
*/ */
public function boot() public function boot()
{ {
$this->registerPolicies();
if(config_cache('pixelfed.oauth_enabled') == true) { if(config_cache('pixelfed.oauth_enabled') == true) {
Passport::routes(null, ['middleware' => ['twofactor', \Fruitcake\Cors\HandleCors::class]]);
Passport::tokensExpireIn(now()->addDays(config('instance.oauth.token_expiration', 356))); Passport::tokensExpireIn(now()->addDays(config('instance.oauth.token_expiration', 356)));
Passport::refreshTokensExpireIn(now()->addDays(config('instance.oauth.refresh_expiration', 400))); Passport::refreshTokensExpireIn(now()->addDays(config('instance.oauth.refresh_expiration', 400)));
Passport::enableImplicitGrant(); Passport::enableImplicitGrant();

View file

@ -6,7 +6,9 @@ use Illuminate\Database\Eloquent\Model;
class Report extends Model class Report extends Model
{ {
protected $dates = ['admin_seen']; protected $casts = [
'admin_seen' => 'datetime'
];
protected $guarded = []; protected $guarded = [];

View file

@ -7,6 +7,7 @@ use App\Profile;
use App\Util\ActivityPub\Helpers; use App\Util\ActivityPub\Helpers;
use App\Util\ActivityPub\HttpSignature; use App\Util\ActivityPub\HttpSignature;
use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\RequestException;
class ActivityPubFetchService class ActivityPubFetchService
{ {
@ -16,14 +17,23 @@ class ActivityPubFetchService
return 0; return 0;
} }
$headers = HttpSignature::instanceActorSign($url, false); $baseHeaders = [
$headers['Accept'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; 'Accept' => 'application/activity+json, application/ld+json',
'User-Agent' => '(Pixelfed/'.config('pixelfed.version').'; +'.config('app.url').')'
];
$headers = HttpSignature::instanceActorSign($url, false, $baseHeaders);
$headers['Accept'] = 'application/activity+json, application/ld+json';
$headers['User-Agent'] = '(Pixelfed/'.config('pixelfed.version').'; +'.config('app.url').')'; $headers['User-Agent'] = '(Pixelfed/'.config('pixelfed.version').'; +'.config('app.url').')';
try { try {
$res = Http::withHeaders($headers) $res = Http::withHeaders($headers)
->timeout(10) ->timeout(30)
->connectTimeout(5)
->retry(3, 500)
->get($url); ->get($url);
} catch (RequestException $e) {
return;
} catch (ConnectionException $e) { } catch (ConnectionException $e) {
return; return;
} catch (Exception $e) { } catch (Exception $e) {

View file

@ -26,7 +26,9 @@ class Status extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['deleted_at']; protected $casts = [
'deleted_at' => 'datetime'
];
protected $guarded = []; protected $guarded = [];

View file

@ -22,7 +22,9 @@ class StoryItem extends Model
* *
* @var array * @var array
*/ */
protected $dates = ['expires_at']; protected $casts = [
'expires_at' => 'datetime'
];
protected $visible = ['id']; protected $visible = ['id'];

View file

@ -17,7 +17,11 @@ class User extends Authenticatable
* *
* @var array * @var array
*/ */
protected $dates = ['deleted_at', 'email_verified_at', '2fa_setup_at']; protected $casts = [
'deleted_at' => 'datetime',
'email_verified_at' => 'datetime',
'2fa_setup_at' => 'datetime'
];
/** /**
* The attributes that are mass assignable. * The attributes that are mass assignable.

View file

@ -130,8 +130,8 @@ class HttpSignature {
$headers = [ $headers = [
'(request-target)' => 'post '.parse_url($url, PHP_URL_PATH), '(request-target)' => 'post '.parse_url($url, PHP_URL_PATH),
'Date' => $date->format('D, d M Y H:i:s \G\M\T'),
'Host' => parse_url($url, PHP_URL_HOST), 'Host' => parse_url($url, PHP_URL_HOST),
'Date' => $date->format('D, d M Y H:i:s \G\M\T'),
]; ];
if($digest) { if($digest) {

View file

@ -178,7 +178,7 @@ class Inbox
switch($obj['type']) { switch($obj['type']) {
case 'Story': case 'Story':
StoryFetch::dispatchNow($this->payload); StoryFetch::dispatchSync($this->payload);
break; break;
} }

View file

@ -5,7 +5,7 @@
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"type": "project", "type": "project",
"require": { "require": {
"php": "^8.0.2|^8.1", "php": "^8.1|^8.2",
"ext-bcmath": "*", "ext-bcmath": "*",
"ext-ctype": "*", "ext-ctype": "*",
"ext-curl": "*", "ext-curl": "*",
@ -16,17 +16,16 @@
"bacon/bacon-qr-code": "^2.0.3", "bacon/bacon-qr-code": "^2.0.3",
"beyondcode/laravel-websockets": "^1.13", "beyondcode/laravel-websockets": "^1.13",
"brick/math": "^0.9.3", "brick/math": "^0.9.3",
"buzz/laravel-h-captcha": "1.0.3", "buzz/laravel-h-captcha": "1.0.4",
"doctrine/dbal": "^2.7", "doctrine/dbal": "^3.0",
"fruitcake/laravel-cors": "^2.0",
"intervention/image": "^2.4", "intervention/image": "^2.4",
"jenssegers/agent": "^2.6", "jenssegers/agent": "^2.6",
"laravel/framework": "^9.0", "laravel/framework": "^10.0",
"laravel/helpers": "^1.1", "laravel/helpers": "^1.1",
"laravel/horizon": "^5.0", "laravel/horizon": "^5.0",
"laravel/passport": "^10.0", "laravel/passport": "^11.0",
"laravel/tinker": "^2.0", "laravel/tinker": "^2.0",
"laravel/ui": "^2.0|^3.4", "laravel/ui": "^4.2",
"league/flysystem-aws-s3-v3": "^3.0", "league/flysystem-aws-s3-v3": "^3.0",
"league/iso3166": "^2.1|^4.0", "league/iso3166": "^2.1|^4.0",
"pbmedia/laravel-ffmpeg": "^8.0", "pbmedia/laravel-ffmpeg": "^8.0",
@ -38,7 +37,7 @@
"predis/predis": "^2.0", "predis/predis": "^2.0",
"spatie/laravel-backup": "^8.0.0", "spatie/laravel-backup": "^8.0.0",
"spatie/laravel-image-optimizer": "^1.7", "spatie/laravel-image-optimizer": "^1.7",
"stevebauman/purify": "4.0.*", "stevebauman/purify": "6.0.*",
"symfony/http-client": "^6.1", "symfony/http-client": "^6.1",
"symfony/http-kernel": "^6.0.0", "symfony/http-kernel": "^6.0.0",
"symfony/mailgun-mailer": "^6.1" "symfony/mailgun-mailer": "^6.1"
@ -46,7 +45,7 @@
"require-dev": { "require-dev": {
"brianium/paratest": "^6.1", "brianium/paratest": "^6.1",
"fakerphp/faker": "^1.20", "fakerphp/faker": "^1.20",
"laravel/telescope": "^4.9", "laravel/telescope": "^4.14",
"mockery/mockery": "^1.0", "mockery/mockery": "^1.0",
"nunomaduro/collision": "^6.1", "nunomaduro/collision": "^6.1",
"phpunit/phpunit": "^9.0" "phpunit/phpunit": "^9.0"
@ -95,6 +94,5 @@
"sort-packages": true, "sort-packages": true,
"optimize-autoloader": true "optimize-autoloader": true
}, },
"minimum-stability": "dev",
"prefer-stable": true "prefer-stable": true
} }

897
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,182 +1,144 @@
<?php <?php
use Stevebauman\Purify\Definitions\Html5Definition;
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Settings | Default Config
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The configuration settings array is passed directly to HTMLPurifier. | This option defines the default config that is provided to HTMLPurifier.
|
| Feel free to add / remove / customize these attributes as you wish.
|
| Documentation: http://htmlpurifier.org/live/configdoc/plain.html
| |
*/ */
'settings' => [ 'default' => 'default',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Core.Encoding | Config sets
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The encoding to convert input to. | Here you may configure various sets of configuration for differentiated use of HTMLPurifier.
| | A specific set of configuration can be applied by calling the "config($name)" method on
| http://htmlpurifier.org/live/configdoc/plain.html#Core.Encoding | a Purify instance. Feel free to add/remove/customize these attributes as you wish.
| |
*/ | Documentation: http://htmlpurifier.org/live/configdoc/plain.html
|
| Core.Encoding The encoding to convert input to.
| HTML.Doctype Doctype to use during filtering.
| HTML.Allowed The allowed HTML Elements with their allowed attributes.
| HTML.ForbiddenElements The forbidden HTML elements. Elements that are listed in this
| string will be removed, however their content will remain.
| CSS.AllowedProperties The Allowed CSS properties.
| AutoFormat.AutoParagraph Newlines are converted in to paragraphs whenever possible.
| AutoFormat.RemoveEmpty Remove empty elements that contribute no semantic information to the document.
|
*/
'Core.Encoding' => 'utf-8', 'configs' => [
/* 'default' => [
|-------------------------------------------------------------------------- 'Core.Encoding' => 'utf-8',
| Core.SerializerPath 'HTML.Doctype' => 'HTML 4.01 Transitional',
|--------------------------------------------------------------------------
|
| The HTML purifier serializer cache path.
|
| http://htmlpurifier.org/live/configdoc/plain.html#Cache.SerializerPath
|
*/
'Cache.SerializerPath' => storage_path('purify'), 'HTML.Allowed' => env('RESTRICT_HTML_TYPES', true) ?
/*
|--------------------------------------------------------------------------
| HTML.Doctype
|--------------------------------------------------------------------------
|
| Doctype to use during filtering.
|
| http://htmlpurifier.org/live/configdoc/plain.html#HTML.Doctype
|
*/
'HTML.Doctype' => 'XHTML 1.0 Transitional',
/*
|--------------------------------------------------------------------------
| HTML.Allowed
|--------------------------------------------------------------------------
|
| The allowed HTML Elements with their allowed attributes.
|
| http://htmlpurifier.org/live/configdoc/plain.html#HTML.Allowed
|
*/
'HTML.Allowed' => env('RESTRICT_HTML_TYPES', true) ?
'a[href|title|rel|class],p[class],span[class],br' : 'a[href|title|rel|class],p[class],span[class],br' :
'a[href|title|rel|class],p[class],span[class],strong,em,del,b,i,s,strike,h1,h2,h3,h4,h5,h6,ul,ol,li,br', 'a[href|title|rel|class],p[class],span[class],strong,em,del,b,i,s,strike,h1,h2,h3,h4,h5,h6,ul,ol,li,br',
'HTML.ForbiddenElements' => '',
'CSS.AllowedProperties' => '',
/* 'AutoFormat.AutoParagraph' => false,
|-------------------------------------------------------------------------- 'AutoFormat.RemoveEmpty' => false,
| HTML.ForbiddenElements
|--------------------------------------------------------------------------
|
| The forbidden HTML elements. Elements that are listed in
| this string will be removed, however their content will remain.
|
| For example if 'p' is inside the string, the string: '<p>Test</p>',
|
| Will be cleaned to: 'Test'
|
| http://htmlpurifier.org/live/configdoc/plain.html#HTML.ForbiddenElements
|
*/
'HTML.ForbiddenElements' => '', 'Attr.AllowedClasses' => [
'h-feed',
'h-entry',
'h-cite',
'h-card',
'p-author',
'p-name',
'p-in-reply-to',
'p-repost-of',
'p-comment',
'u-photo',
'u-uid',
'u-url',
'dt-published',
'e-content',
'mention',
'hashtag',
'ellipsis',
'invisible'
],
/* 'Attr.AllowedRel' => [
|-------------------------------------------------------------------------- 'noreferrer',
| CSS.AllowedProperties 'noopener',
|-------------------------------------------------------------------------- 'nofollow'
| ],
| The Allowed CSS properties.
|
| http://htmlpurifier.org/live/configdoc/plain.html#CSS.AllowedProperties
|
*/
'CSS.AllowedProperties' => '', 'HTML.TargetBlank' => true,
/* 'HTML.Nofollow' => true,
|--------------------------------------------------------------------------
| AutoFormat.AutoParagraph
|--------------------------------------------------------------------------
|
| The Allowed CSS properties.
|
| This directive turns on auto-paragraphing, where double
| newlines are converted in to paragraphs whenever possible.
|
| http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.AutoParagraph
|
*/
'AutoFormat.AutoParagraph' => false, 'URI.DefaultScheme' => 'https',
/* 'URI.DisableExternalResources' => true,
|--------------------------------------------------------------------------
| AutoFormat.RemoveEmpty
|--------------------------------------------------------------------------
|
| When enabled, HTML Purifier will attempt to remove empty
| elements that contribute no semantic information to the document.
|
| http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.RemoveEmpty
|
*/
'AutoFormat.RemoveEmpty' => false, 'URI.DisableResources' => true,
'Attr.AllowedClasses' => [ 'URI.AllowedSchemes' => [
'h-feed', 'http' => true,
'h-entry', 'https' => true,
'h-cite', ],
'h-card',
'p-author', 'URI.HostBlacklist' => config('costar.enabled') ? config('costar.domain.block') : [],
'p-name',
'p-in-reply-to',
'p-repost-of',
'p-comment',
'u-photo',
'u-uid',
'u-url',
'dt-published',
'e-content',
'mention',
'hashtag',
'ellipsis',
'invisible'
], ],
'Attr.AllowedRel' => [
'noreferrer',
'noopener',
'nofollow'
],
'HTML.TargetBlank' => true,
'HTML.Nofollow' => true,
'URI.DefaultScheme' => 'https',
'URI.DisableExternalResources' => true,
'URI.DisableResources' => true,
'URI.AllowedSchemes' => [
'http' => true,
'https' => true,
],
'URI.HostBlacklist' => config('costar.enabled') ? config('costar.domain.block') : [],
], ],
/*
|--------------------------------------------------------------------------
| HTMLPurifier definitions
|--------------------------------------------------------------------------
|
| Here you may specify a class that augments the HTML definitions used by
| HTMLPurifier. Additional HTML5 definitions are provided out of the box.
| When specifying a custom class, make sure it implements the interface:
|
| \Stevebauman\Purify\Definitions\Definition
|
| Note that these definitions are applied to every Purifier instance.
|
| Documentation: http://htmlpurifier.org/docs/enduser-customize.html
|
*/
'definitions' => Html5Definition::class,
/*
|--------------------------------------------------------------------------
| Serializer
|--------------------------------------------------------------------------
|
| The storage implementation where HTMLPurifier can store its serializer files.
| If the filesystem cache is in use, the path must be writable through the
| storage disk by the web server, otherwise an exception will be thrown.
|
*/
'serializer' => [
'driver' => env('CACHE_DRIVER', 'file'),
'cache' => \Stevebauman\Purify\Cache\CacheDefinitionCache::class,
],
// 'serializer' => [
// 'disk' => env('FILESYSTEM_DISK', 'local'),
// 'path' => 'purify',
// 'cache' => \Stevebauman\Purify\Cache\FilesystemDefinitionCache::class,
// ],
]; ];

View file

@ -1,19 +0,0 @@
<?php
namespace Tests\Feature;
use Tests\TestCase;
class InstalledTest extends TestCase
{
/** @test */
public function nodeinfo_api(): void
{
$response = $this->get('/.well-known/nodeinfo');
$response->assertJson([
'links' => [
['rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.0'],
],
]);
}
}