mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-12-26 15:03:17 +00:00
Update ap inbox
This commit is contained in:
parent
8cc91babd7
commit
29961c4a80
3 changed files with 217 additions and 0 deletions
88
app/Jobs/ProfilePipeline/HandleUpdateActivity.php
Normal file
88
app/Jobs/ProfilePipeline/HandleUpdateActivity.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs\ProfilePipeline;
|
||||
|
||||
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\Avatar;
|
||||
use App\Profile;
|
||||
use App\Util\ActivityPub\Helpers;
|
||||
use Purify;
|
||||
use App\Jobs\AvatarPipeline\RemoteAvatarFetch;
|
||||
use App\Util\Lexer\Autolink;
|
||||
|
||||
class HandleUpdateActivity implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $payload;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($payload)
|
||||
{
|
||||
$this->payload = $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$payload = $this->payload;
|
||||
|
||||
if(empty($payload) || !isset($payload['actor'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$profile = Profile::whereRemoteUrl($payload['actor'])->first();
|
||||
|
||||
if(!$profile || $profile->domain === null || $profile->private_key) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($profile->sharedInbox == null || $profile->sharedInbox != $payload['object']['endpoints']['sharedInbox']) {
|
||||
$profile->sharedInbox = $payload['object']['endpoints']['sharedInbox'];
|
||||
}
|
||||
|
||||
if($profile->public_key !== $payload['object']['publicKey']['publicKeyPem']) {
|
||||
$profile->public_key = $payload['object']['publicKey']['publicKeyPem'];
|
||||
}
|
||||
|
||||
if($profile->bio !== $payload['object']['summary']) {
|
||||
$len = strlen(strip_tags($payload['object']['summary']));
|
||||
if($len) {
|
||||
if($len > 500) {
|
||||
$updated = strip_tags($payload['object']['summary']);
|
||||
$updated = substr($updated, 0, config('pixelfed.max_bio_length'));
|
||||
$profile->bio = Autolink::create()->autolink($updated);
|
||||
} else {
|
||||
$profile->bio = Purify::clean($payload['object']['summary']);
|
||||
}
|
||||
} else {
|
||||
$profile->bio = null;
|
||||
}
|
||||
}
|
||||
|
||||
if($profile->name !== $payload['object']['name']) {
|
||||
$profile->name = Purify::clean(substr($payload['object']['name'], 0, config('pixelfed.max_name_length')));
|
||||
}
|
||||
|
||||
if($profile->isDirty()) {
|
||||
$profile->save();
|
||||
}
|
||||
|
||||
RemoteAvatarFetch::dispatch($profile)->onQueue('low');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ use App\Jobs\DeletePipeline\DeleteRemoteStatusPipeline;
|
|||
use App\Jobs\StoryPipeline\StoryExpire;
|
||||
use App\Jobs\StoryPipeline\StoryFetch;
|
||||
use App\Jobs\StatusPipeline\StatusRemoteUpdatePipeline;
|
||||
use App\Jobs\ProfilePipeline\HandleUpdateActivity;
|
||||
|
||||
use App\Util\ActivityPub\Validator\Accept as AcceptValidator;
|
||||
use App\Util\ActivityPub\Validator\Add as AddValidator;
|
||||
|
@ -36,6 +37,7 @@ use App\Util\ActivityPub\Validator\Announce as AnnounceValidator;
|
|||
use App\Util\ActivityPub\Validator\Follow as FollowValidator;
|
||||
use App\Util\ActivityPub\Validator\Like as LikeValidator;
|
||||
use App\Util\ActivityPub\Validator\UndoFollow as UndoFollowValidator;
|
||||
use App\Util\ActivityPub\Validator\UpdatePersonValidator;
|
||||
|
||||
use App\Services\PollService;
|
||||
use App\Services\FollowerService;
|
||||
|
@ -1217,10 +1219,18 @@ class Inbox
|
|||
return;
|
||||
}
|
||||
|
||||
if(!Helpers::validateUrl($activity['id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($activity['type'] === 'Note') {
|
||||
if(Status::whereObjectUrl($activity['id'])->exists()) {
|
||||
StatusRemoteUpdatePipeline::dispatch($activity);
|
||||
}
|
||||
} else if ($activity['type'] === 'Person') {
|
||||
if(UpdatePersonValidator::validate($this->payload)) {
|
||||
HandleUpdateActivity::dispatch($this->payload)->onQueue('low');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
119
app/Util/ActivityPub/Validator/UpdatePersonValidator.php
Normal file
119
app/Util/ActivityPub/Validator/UpdatePersonValidator.php
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\ActivityPub\Validator;
|
||||
|
||||
use Validator;
|
||||
use Closure;
|
||||
use Illuminate\Validation\Rule;
|
||||
use \App\Rules\SameHostDomain;
|
||||
|
||||
class UpdatePersonValidator
|
||||
{
|
||||
public static function validate($payload)
|
||||
{
|
||||
$valid = Validator::make($payload, [
|
||||
'@context' => 'required',
|
||||
'id' => 'required|string|url',
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in(['Update'])
|
||||
],
|
||||
'actor' => 'required|url',
|
||||
'object' => 'required',
|
||||
'object.id' => [
|
||||
'required',
|
||||
'url',
|
||||
'same:actor',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.type' => [
|
||||
'required',
|
||||
Rule::in(['Person'])
|
||||
],
|
||||
'object.publicKey' => 'required',
|
||||
'object.publicKey.id' => [
|
||||
'required',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.publicKey.owner' => [
|
||||
'required',
|
||||
'url',
|
||||
'same:actor',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.publicKey.publicKeyPem' => 'required|string',
|
||||
'object.url' => [
|
||||
'required',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.summary' => 'required|string|nullable',
|
||||
'object.preferredUsername' => 'required|string',
|
||||
'object.name' => 'required|string|nullable',
|
||||
'object.inbox' => [
|
||||
'required',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.outbox' => [
|
||||
'required',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.following' => [
|
||||
'required',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.followers' => [
|
||||
'required',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
],
|
||||
'object.manuallyApprovesFollowers' => 'required',
|
||||
'object.icon' => 'sometimes|nullable',
|
||||
'object.icon.type' => 'sometimes|required_with:object.icon.url,object.icon.mediaType|in:Image',
|
||||
'object.icon.url' => 'sometimes|required_with:object.icon.type,object.icon.mediaType|url',
|
||||
'object.icon.mediaType' => 'sometimes|required_with:object.icon.url,object.icon.type|in:image/jpeg,image/png,image/jpg',
|
||||
'object.endpoints' => 'sometimes',
|
||||
'object.endpoints.sharedInbox' => [
|
||||
'sometimes',
|
||||
'url',
|
||||
function (string $attribute, mixed $value, Closure $fail) use($payload) {
|
||||
self::sameHost($attribute, $value, $fail, $payload['actor']);
|
||||
},
|
||||
]
|
||||
])->passes();
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
public static function sameHost(string $attribute, mixed $value, Closure $fail, string $comparedHost)
|
||||
{
|
||||
if(empty($value)) {
|
||||
$fail('The ' . $attribute . ' is invalid or empty');
|
||||
}
|
||||
$host = parse_url($value, PHP_URL_HOST);
|
||||
$idHost = parse_url($comparedHost, PHP_URL_HOST);
|
||||
if ($host !== $idHost) {
|
||||
$fail('The ' . $attribute . ' is invalid');
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue