forked from mirror/pixelfed
commit
30b5f43fc0
|
@ -42,9 +42,11 @@ class CatchUnoptimizedMedia extends Command
|
|||
{
|
||||
DB::transaction(function() {
|
||||
Media::whereNull('processed_at')
|
||||
->where('skip_optimize', '!=', true)
|
||||
->whereNull('remote_url')
|
||||
->whereNotNull('status_id')
|
||||
->whereNotNull('media_path')
|
||||
->where('created_at', '>', now()->subHours(1))
|
||||
->whereIn('mime', [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Profile;
|
||||
use App\User;
|
||||
|
||||
class FixSoftDeletedProfile extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'fix:sdprofile';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$profiles = Profile::whereNull('domain')
|
||||
->withTrashed()
|
||||
->where('deleted_at', '>', now()->subDays(14))
|
||||
->whereNull('status')
|
||||
->pluck('username');
|
||||
|
||||
if($profiles->count() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach($profiles as $p) {
|
||||
if(User::whereUsername($p)->first()->status == null) {
|
||||
$pro = Profile::withTrashed()->whereUsername($p)->firstOrFail();
|
||||
$pro->deleted_at = null;
|
||||
$pro->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\InstanceActor;
|
||||
use Cache;
|
||||
|
||||
class GenerateInstanceActor extends Command
|
||||
{
|
||||
protected $signature = 'instance:actor';
|
||||
protected $description = 'Generate instance actor';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
if(Schema::hasTable('instance_actors') == false) {
|
||||
$this->line(' ');
|
||||
$this->error('Missing instance_actors table.');
|
||||
$this->info('Run "php artisan migrate" and try again.');
|
||||
$this->line(' ');
|
||||
exit;
|
||||
}
|
||||
|
||||
if(InstanceActor::exists()) {
|
||||
$this->line(' ');
|
||||
$this->error('Instance actor already exists!');
|
||||
$this->line(' ');
|
||||
$actor = InstanceActor::whereNotNull('public_key')
|
||||
->whereNotNull('private_key')
|
||||
->firstOrFail();
|
||||
Cache::rememberForever(InstanceActor::PKI_PUBLIC, function() use($actor) {
|
||||
return $actor->public_key;
|
||||
});
|
||||
|
||||
Cache::rememberForever(InstanceActor::PKI_PRIVATE, function() use($actor) {
|
||||
return $actor->private_key;
|
||||
});
|
||||
exit;
|
||||
}
|
||||
|
||||
$pkiConfig = [
|
||||
'digest_alg' => 'sha512',
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
];
|
||||
$pki = openssl_pkey_new($pkiConfig);
|
||||
openssl_pkey_export($pki, $pki_private);
|
||||
$pki_public = openssl_pkey_get_details($pki);
|
||||
$pki_public = $pki_public['key'];
|
||||
|
||||
$actor = new InstanceActor();
|
||||
$actor->public_key = $pki_public;
|
||||
$actor->private_key = $pki_private;
|
||||
$actor->save();
|
||||
|
||||
Cache::rememberForever(InstanceActor::PKI_PUBLIC, function() use($actor) {
|
||||
return $actor->public_key;
|
||||
});
|
||||
|
||||
Cache::rememberForever(InstanceActor::PKI_PRIVATE, function() use($actor) {
|
||||
return $actor->private_key;
|
||||
});
|
||||
|
||||
$this->info('Instance actor succesfully generated. You do not need to run this command again.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -25,13 +25,10 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('media:optimize')
|
||||
->hourly();
|
||||
$schedule->command('media:gc')
|
||||
->hourly();
|
||||
$schedule->command('media:optimize')->hourly();
|
||||
$schedule->command('media:gc')->hourly();
|
||||
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
||||
$schedule->command('story:gc')->everyFiveMinutes();
|
||||
$schedule->command('fix:sdprofile')->everyFiveMinutes();
|
||||
$schedule->command('gc:failedjobs')->dailyAt(3);
|
||||
$schedule->command('gc:passwordreset')->dailyAt('09:41');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\InstanceActor;
|
||||
use Cache;
|
||||
|
||||
class InstanceActorController extends Controller
|
||||
{
|
||||
public function profile()
|
||||
{
|
||||
$res = Cache::rememberForever(InstanceActor::PROFILE_KEY, function() {
|
||||
$res = (new InstanceActor())->first()->getActor();
|
||||
return json_encode($res);
|
||||
});
|
||||
return response($res)->header('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function inbox()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public function outbox()
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => config('app.url') . '/i/actor/outbox',
|
||||
'type' => 'OrderedCollection',
|
||||
'totalItems' => 0,
|
||||
'first' => config('app.url') . '/i/actor/outbox?page=true',
|
||||
'last' => config('app.url') . '/i/actor/outbox?min_id=0page=true'
|
||||
];
|
||||
return response()->json($res);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class InstanceActor extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
const PROFILE_BASE = '/i/actor';
|
||||
const KEY_ID = '/i/actor#main-key';
|
||||
const PROFILE_KEY = 'federation:_v2:instance:actor:profile';
|
||||
const PKI_PUBLIC = 'federation:_v1:instance:actor:profile:pki_public';
|
||||
const PKI_PRIVATE = 'federation:_v1:instance:actor:profile:pki_private';
|
||||
|
||||
public function permalink($suffix = '')
|
||||
{
|
||||
return url(self::PROFILE_BASE . $suffix);
|
||||
}
|
||||
|
||||
public function getActor()
|
||||
{
|
||||
return [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $this->permalink(),
|
||||
'type' => 'Application',
|
||||
'inbox' => $this->permalink('/inbox'),
|
||||
'outbox' => $this->permalink('/outbox'),
|
||||
'preferredUsername' => config('pixelfed.domain.app'),
|
||||
'publicKey' => [
|
||||
'id' => $this->permalink('#main-key'),
|
||||
'owner' => $this->permalink(),
|
||||
'publicKeyPem' => $this->public_key
|
||||
],
|
||||
'manuallyApprovesFollowers' => true,
|
||||
'url' => route('help.instance-actor')
|
||||
];
|
||||
}
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace App\Util\ActivityPub;
|
||||
|
||||
use Log;
|
||||
use Cache, Log;
|
||||
use App\Models\InstanceActor;
|
||||
use App\Profile;
|
||||
use \DateTime;
|
||||
|
||||
|
@ -32,6 +33,29 @@ class HttpSignature {
|
|||
return self::_headersToCurlArray($headers);
|
||||
}
|
||||
|
||||
public static function instanceActorSign($url, $body = false, $addlHeaders = [])
|
||||
{
|
||||
$keyId = config('app.url') . '/i/actor#main-key';
|
||||
$privateKey = Cache::rememberForever(InstanceActor::PKI_PRIVATE, function() {
|
||||
return InstanceActor::first()->private_key;
|
||||
});
|
||||
if($body) {
|
||||
$digest = self::_digest($body);
|
||||
}
|
||||
$headers = self::_headersToSign($url, $body ? $digest : false);
|
||||
$headers = array_merge($headers, $addlHeaders);
|
||||
$stringToSign = self::_headersToSigningString($headers);
|
||||
$signedHeaders = implode(' ', array_map('strtolower', array_keys($headers)));
|
||||
$key = openssl_pkey_get_private($privateKey);
|
||||
openssl_sign($stringToSign, $signature, $key, OPENSSL_ALGO_SHA256);
|
||||
$signature = base64_encode($signature);
|
||||
$signatureHeader = 'keyId="'.$keyId.'",headers="'.$signedHeaders.'",algorithm="rsa-sha256",signature="'.$signature.'"';
|
||||
unset($headers['(request-target)']);
|
||||
$headers['Signature'] = $signatureHeader;
|
||||
|
||||
return self::_headersToCurlArray($headers);
|
||||
}
|
||||
|
||||
public static function parseSignatureHeader($signature) {
|
||||
$parts = explode(',', $signature);
|
||||
$signatureData = [];
|
||||
|
|
|
@ -98,6 +98,8 @@ class RestrictedNames
|
|||
'aboutus',
|
||||
'about-us',
|
||||
'abuse',
|
||||
'actor',
|
||||
'actors',
|
||||
'account',
|
||||
'admins',
|
||||
'api',
|
||||
|
@ -179,6 +181,7 @@ class RestrictedNames
|
|||
'help-center_',
|
||||
'help_center-',
|
||||
'i',
|
||||
'instance',
|
||||
'inbox',
|
||||
'img',
|
||||
'imgs',
|
||||
|
@ -208,6 +211,17 @@ class RestrictedNames
|
|||
'media',
|
||||
'menu',
|
||||
'music',
|
||||
'my2020',
|
||||
'my2021',
|
||||
'my2022',
|
||||
'my2023',
|
||||
'my2024',
|
||||
'my2025',
|
||||
'my2026',
|
||||
'my2027',
|
||||
'my2028',
|
||||
'my2029',
|
||||
'my2030',
|
||||
'n',
|
||||
'news',
|
||||
'new',
|
||||
|
|
|
@ -8,7 +8,7 @@ use Illuminate\Support\Str;
|
|||
class Config {
|
||||
|
||||
public static function get() {
|
||||
return Cache::remember('api:site:configuration:_v0', now()->addHours(30), function() {
|
||||
return Cache::remember('api:site:configuration:_v0.1', now()->addHours(30), function() {
|
||||
return [
|
||||
'open_registration' => config('pixelfed.open_registration'),
|
||||
'uploader' => [
|
||||
|
@ -34,7 +34,8 @@ class Config {
|
|||
'ab' => [
|
||||
'lc' => config('exp.lc'),
|
||||
'rec' => config('exp.rec'),
|
||||
'loops' => config('exp.loops')
|
||||
'loops' => config('exp.loops'),
|
||||
'top' => config('exp.top')
|
||||
],
|
||||
|
||||
'site' => [
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
return [
|
||||
|
||||
'lc' => env('EXP_LC', false),
|
||||
'rec' => env('EXP_REC', false),
|
||||
'loops' => env('EXP_LOOPS', false),
|
||||
'rec' => false,
|
||||
'loops' => false,
|
||||
'top' => env('EXP_TOP', false),
|
||||
];
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateInstanceActorsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('instance_actors', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->text('private_key')->nullable();
|
||||
$table->text('public_key')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('instance_actors');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue