Add hooks for ReportController

This commit is contained in:
Pig Fang 2019-11-20 15:01:09 +08:00
parent ee872104b0
commit bf4623c6ef
2 changed files with 154 additions and 7 deletions

View File

@ -5,12 +5,15 @@ namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Report;
use App\Models\Texture;
use App\Services\Filter;
use App\Services\Rejection;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Contracts\Events\Dispatcher;
class ReportController extends Controller
{
public function submit(Request $request)
public function submit(Request $request, Dispatcher $dispatcher, Filter $filter)
{
$data = $this->validate($request, [
'tid' => 'required|exists:textures',
@ -18,6 +21,13 @@ class ReportController extends Controller
]);
$reporter = auth()->user();
$can = $filter->apply('user_can_report', true, [$data['tid'], $data['reason'], $reporter]);
if ($can instanceof Rejection) {
return json($can->getReason(), 1);
}
$dispatcher->dispatch('report.submitting', [$data['tid'], $data['reason'], $reporter]);
if (Report::where('reporter', $reporter->uid)->where('tid', $data['tid'])->count() > 0) {
return json(trans('skinlib.report.duplicate'), 1);
}
@ -37,6 +47,8 @@ class ReportController extends Controller
$report->status = Report::PENDING;
$report->save();
$dispatcher->dispatch('report.submitted', [$report]);
return json(trans('skinlib.report.success'), 0);
}
@ -81,15 +93,18 @@ class ReportController extends Controller
];
}
public function review(Request $request)
public function review(Request $request, Dispatcher $dispatcher)
{
$data = $this->validate($request, [
'id' => 'required|exists:reports',
'action' => ['required', Rule::in(['delete', 'ban', 'reject'])],
]);
$action = $data['action'];
$report = Report::find($data['id']);
if ($data['action'] == 'reject') {
$dispatcher->dispatch('report.reviewing', [$report, $action]);
if ($action == 'reject') {
if (
$report->informer &&
($score = option('reporter_score_modification', 0)) > 0 &&
@ -101,13 +116,17 @@ class ReportController extends Controller
$report->status = Report::REJECTED;
$report->save();
$dispatcher->dispatch('report.rejected', [$report]);
return json(trans('general.op-success'), 0, ['status' => Report::REJECTED]);
}
switch ($data['action']) {
switch ($action) {
case 'delete':
if ($report->texture) {
$report->texture->delete();
$texture = $report->texture;
if ($texture) {
$texture->delete();
$dispatcher->dispatch('texture.deleted', [$texture]);
} else {
// The texture has been deleted by its uploader
// We will return the score, but will not give the informer any reward
@ -115,6 +134,8 @@ class ReportController extends Controller
$report->status = Report::RESOLVED;
$report->save();
$dispatcher->dispatch('report.resolved', [$report, $action]);
return json(trans('general.texture-deleted'), 0, ['status' => Report::RESOLVED]);
}
break;
@ -128,6 +149,7 @@ class ReportController extends Controller
}
$uploader->permission = User::BANNED;
$uploader->save();
$dispatcher->dispatch('user.banned', [$uploader]);
break;
}
@ -136,6 +158,8 @@ class ReportController extends Controller
$report->status = Report::RESOLVED;
$report->save();
$dispatcher->dispatch('report.resolved', [$report, $action]);
return json(trans('general.op-success'), 0, ['status' => Report::RESOLVED]);
}

View File

@ -2,9 +2,12 @@
namespace Tests;
use Event;
use App\Models\User;
use App\Models\Report;
use App\Models\Texture;
use App\Services\Filter;
use App\Services\Rejection;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ReportControllerTest extends TestCase
@ -13,6 +16,9 @@ class ReportControllerTest extends TestCase
public function testSubmit()
{
Event::fake();
$filter = resolve(Filter::class);
$user = factory(User::class)->create();
$texture = factory(Texture::class)->create();
@ -38,9 +44,24 @@ class ReportControllerTest extends TestCase
'code' => 1,
'message' => trans('skinlib.upload.lack-score'),
]);
option(['reporter_score_modification' => 5]);
// Rejection
$filter->add(
'user_can_report',
function ($can, $tid, $reason, $reporter) use ($texture, $user) {
$this->assertEquals($texture->tid, $tid);
$this->assertEquals('reason', $reason);
$this->assertEquals($user->uid, $reporter->uid);
return new Rejection('rejected');
}
);
$this->postJson('/skinlib/report', ['tid' => $texture->tid, 'reason' => 'reason'])
->assertJson(['code' => 1, 'message' => 'rejected']);
$filter->remove('user_can_report');
// Success
option(['reporter_score_modification' => 5]);
$this->postJson('/skinlib/report', ['tid' => $texture->tid, 'reason' => 'reason'])
->assertJson([
'code' => 0,
@ -53,6 +74,24 @@ class ReportControllerTest extends TestCase
$this->assertEquals($texture->uploader, $report->uploader);
$this->assertEquals('reason', $report->reason);
$this->assertEquals(Report::PENDING, $report->status);
Event::assertDispatched('report.submitting', function ($event, $payload) use ($texture, $user) {
[$tid, $reason, $reporter] = $payload;
$this->assertEquals($texture->tid, $tid);
$this->assertEquals('reason', $reason);
$this->assertEquals($user->uid, $reporter->uid);
return true;
});
Event::assertDispatched('report.submitted', function ($event, $payload) use ($texture, $user) {
[$report] = $payload;
$this->assertEquals($texture->tid, $report->tid);
$this->assertEquals($texture->uploader, $report->uploader);
$this->assertEquals($user->uid, $report->reporter);
$this->assertEquals('reason', $report->reason);
$this->assertEquals(Report::PENDING, $report->status);
return true;
});
// Prevent duplication
$this->postJson('/skinlib/report', ['tid' => $texture->tid, 'reason' => 'reason'])
@ -114,6 +153,8 @@ class ReportControllerTest extends TestCase
public function testReview()
{
Event::fake();
$admin = factory(User::class, 'admin')->create();
$texture = factory(Texture::class)->create(['uploader' => $admin->uid]);
@ -146,10 +187,20 @@ class ReportControllerTest extends TestCase
// Allow to process again
$this->postJson('/admin/reports', ['id' => $report->id, 'action' => 'reject'])
->assertJson(['code' => 0]);
$id = $report->id;
Event::assertDispatched('report.reviewing', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('reject', $action);
return true;
});
}
public function testReviewReject()
{
Event::fake();
$uploader = factory(User::class)->create();
$reporter = factory(User::class)->create();
$admin = factory(User::class, 'admin')->create();
@ -163,6 +214,7 @@ class ReportControllerTest extends TestCase
$report->status = Report::PENDING;
$report->save();
$report->refresh();
$id = $report->id;
// Should not cost score
$score = $reporter->score;
@ -177,6 +229,19 @@ class ReportControllerTest extends TestCase
$reporter->refresh();
$this->assertEquals(Report::REJECTED, $report->status);
$this->assertEquals($score, $reporter->score);
Event::assertDispatched('report.reviewing', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('reject', $action);
return true;
});
Event::assertDispatched('report.rejected', function ($event, $payload) use ($id) {
[$report] = $payload;
$this->assertEquals($id, $report->id);
return true;
});
// Should cost score
$report->status = Report::PENDING;
@ -191,6 +256,8 @@ class ReportControllerTest extends TestCase
public function testReviewDelete()
{
Event::fake();
$uploader = factory(User::class)->create();
$reporter = factory(User::class)->create();
$admin = factory(User::class, 'admin')->create();
@ -204,6 +271,8 @@ class ReportControllerTest extends TestCase
$report->status = Report::PENDING;
$report->save();
$report->refresh();
$id = $report->id;
$tid = $texture->tid;
option([
'reporter_score_modification' => -7,
@ -223,10 +292,32 @@ class ReportControllerTest extends TestCase
$this->assertEquals(Report::RESOLVED, $report->status);
$this->assertNull(Texture::find($texture->tid));
$this->assertEquals($score + 7, $reporter->score);
Event::assertDispatched('report.reviewing', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('delete', $action);
return true;
});
Event::assertDispatched('texture.deleted', function ($event, $payload) use ($tid) {
[$texture] = $payload;
$this->assertEquals($tid, $texture->tid);
return true;
});
Event::assertDispatched('report.resolved', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('delete', $action);
return true;
});
}
public function testReviewDeleteNonExistentTexture()
{
Event::fake();
$uploader = factory(User::class)->create();
$reporter = factory(User::class)->create();
$admin = factory(User::class, 'admin')->create();
@ -240,6 +331,7 @@ class ReportControllerTest extends TestCase
$report->status = Report::PENDING;
$report->save();
$report->refresh();
$id = $report->id;
option([
'reporter_reward_score' => 6,
@ -257,10 +349,20 @@ class ReportControllerTest extends TestCase
$report->refresh();
$this->assertEquals(Report::RESOLVED, $report->status);
$this->assertEquals($score, $reporter->score);
Event::assertNotDispatched('texture.deleted');
Event::assertDispatched('report.resolved', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('delete', $action);
return true;
});
}
public function testReviewBan()
{
Event::fake();
$uploader = factory(User::class)->create();
$reporter = factory(User::class)->create();
$admin = factory(User::class, 'admin')->create();
@ -274,6 +376,7 @@ class ReportControllerTest extends TestCase
$report->status = Report::PENDING;
$report->save();
$report->refresh();
$id = $report->id;
// Uploader should be banned
option(['reporter_reward_score' => 6]);
@ -306,6 +409,26 @@ class ReportControllerTest extends TestCase
$report->refresh();
$this->assertEquals(Report::PENDING, $report->status);
$this->assertEquals(User::ADMIN, $uploader->permission);
Event::assertDispatched('report.reviewing', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('ban', $action);
return true;
});
Event::assertDispatched('user.banned', function ($event, $payload) use ($uploader) {
[$up] = $payload;
$this->assertEquals($uploader->uid, $up->uid);
return true;
});
Event::assertDispatched('report.resolved', function ($event, $payload) use ($id) {
[$report, $action] = $payload;
$this->assertEquals($id, $report->id);
$this->assertEquals('ban', $action);
return true;
});
// Uploader has deleted its account
$report->uploader = -1;