Store instance notes as array to match model cast and domain-block API

pull/7838/head
Ashley 1 week ago
parent b33a348ddb
commit 952dc87768

@ -197,9 +197,16 @@ trait AdminInstanceController
'banned',
'auto_cw',
'unlisted',
'notes',
]));
// notes is stored as an array to match the model cast and the
// domain-block API, so normalize the submitted string before saving
if ($request->has('notes')) {
$notes = $request->input('notes');
$instance->notes = filled($notes) ? [$notes] : null;
$instance->save();
}
InstanceService::refresh();
return new AdminInstance($instance);
@ -226,7 +233,8 @@ trait AdminInstanceController
$instance->auto_cw = $request->input('auto_cw');
$instance->unlisted = $request->input('unlisted');
$instance->manually_added = true;
$instance->notes = $request->input('notes');
$notes = $request->input('notes');
$instance->notes = filled($notes) ? [$notes] : null;
$instance->save();
InstanceService::refresh();

@ -44,7 +44,7 @@ class DomainBlockResource extends JsonResource
// We don't have data for these fields
'reject_media' => false,
'reject_reports' => false,
'private_comment' => $this->notes ? implode('; ', $this->notes) : null,
'private_comment' => $this->notes ? (is_array($this->notes) ? implode('; ', $this->notes) : (string) $this->notes) : null,
'public_comment' => $this->limit_reason,
'obfuscate' => false,
];

@ -0,0 +1,87 @@
<?php
use App\Http\Controllers\AdminController;
use App\Models\Instance;
use App\Models\User;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Laravel\Passport\Passport;
uses(LazilyRefreshDatabase::class);
describe('instance notes data type', function () {
it('stores admin-saved notes as an array and serves them through the domain_blocks API', function () {
$instance = Instance::create([
'domain' => 'bad.example',
'banned' => false,
'unlisted' => false,
]);
$request = Request::create('/i/admin/instances/update', 'POST', [
'id' => $instance->id,
'banned' => 1,
'unlisted' => 1,
'notes' => 'spam ring',
]);
app(AdminController::class)->postInstanceUpdateApi($request);
$instance->refresh();
expect(is_array($instance->notes))->toBeTrue();
expect($instance->notes)->toBe(['spam ring']);
$admin = User::factory()->admin()->create();
$admin->refresh();
Passport::actingAs($admin, ['admin:read']);
$this->getJson('/api/v1/admin/domain_blocks')
->assertOk()
->assertJsonFragment(['private_comment' => 'spam ring']);
$this->getJson('/api/v1/admin/domain_blocks/'.$instance->id)
->assertOk()
->assertJsonFragment(['private_comment' => 'spam ring']);
});
it('lets an API-created array block be re-saved through the admin path without a 422', function () {
$instance = Instance::create([
'domain' => 'bad2.example',
'banned' => true,
'notes' => ['via api'],
]);
$request = Request::create('/i/admin/instances/update', 'POST', [
'id' => $instance->id,
'banned' => 1,
'notes' => 'updated note',
]);
app(AdminController::class)->postInstanceUpdateApi($request);
$instance->refresh();
expect(is_array($instance->notes))->toBeTrue();
expect($instance->notes)->toBe(['updated note']);
});
it('does not 500 the index when a legacy scalar note is present', function () {
$instance = Instance::create([
'domain' => 'legacy.example',
'banned' => true,
]);
// mimic a pre-fix row: the array cast json_encodes a scalar string,
// so a legacy value is stored as a JSON scalar and decodes back to a string
DB::table('instances')
->where('id', $instance->id)
->update(['notes' => json_encode('legacy string')]);
$admin = User::factory()->admin()->create();
$admin->refresh();
Passport::actingAs($admin, ['admin:read']);
$this->getJson('/api/v1/admin/domain_blocks')
->assertOk()
->assertJsonFragment(['private_comment' => 'legacy string']);
});
});
Loading…
Cancel
Save