Add more events and filters

This commit is contained in:
Pig Fang 2019-09-04 19:31:44 +08:00
parent 9ccb620fe4
commit 3fc176e07a
2 changed files with 139 additions and 22 deletions

View File

@ -11,9 +11,12 @@ use Session;
use Carbon\Carbon;
use App\Models\User;
use App\Models\Texture;
use App\Services\Filter;
use App\Services\Rejection;
use Illuminate\Http\Request;
use App\Mail\EmailVerification;
use App\Events\UserProfileUpdated;
use Illuminate\Contracts\Events\Dispatcher;
class UserController extends Controller
{
@ -205,10 +208,18 @@ class UserController extends Controller
]);
}
public function handleProfile(Request $request, User $users)
public function handleProfile(Request $request, Filter $filter, Dispatcher $dispatcher)
{
$action = $request->input('action', '');
$user = Auth::user();
$addition = $request->except('action');
$can = $filter->apply('user_can_edit_profile', true, [$action, $addition]);
if ($can instanceof Rejection) {
return json($can->getReason(), 1);
}
$dispatcher->dispatch('user.profile.updating', [$user, $action, $addition]);
switch ($action) {
case 'nickname':
@ -223,6 +234,8 @@ class UserController extends Controller
$nickname = $request->input('new_nickname');
$user->nickname = $nickname;
$user->save();
$dispatcher->dispatch('user.profile.updated', [$user, $action, $addition]);
event(new UserProfileUpdated($action, $user));
return json(trans('user.profile.nickname.success', ['nickname' => $nickname]), 0);
@ -238,6 +251,7 @@ class UserController extends Controller
}
if ($user->changePassword($request->input('new_password'))) {
$dispatcher->dispatch('user.profile.updated', [$user, $action, $addition]);
event(new UserProfileUpdated($action, $user));
Auth::logout();
@ -265,6 +279,7 @@ class UserController extends Controller
$user->verified = false;
$user->save();
$dispatcher->dispatch('user.profile.updated', [$user, $action, $addition]);
event(new UserProfileUpdated($action, $user));
Auth::logout();
@ -286,7 +301,10 @@ class UserController extends Controller
Auth::logout();
$dispatcher->dispatch('user.deleting', [$user]);
if ($user->delete()) {
$dispatcher->dispatch('user.deleted', [$user]);
session()->flush();
return json(trans('user.profile.delete.success'), 0);
@ -302,35 +320,39 @@ class UserController extends Controller
// @codeCoverageIgnore
/**
* Set user avatar.
*
* @param Request $request
*/
public function setAvatar(Request $request)
public function setAvatar(Request $request, Filter $filter, Dispatcher $dispatcher)
{
$this->validate($request, [
'tid' => 'required|integer',
]);
$this->validate($request, ['tid' => 'required|integer']);
$tid = $request->input('tid');
$user = auth()->user();
$can = $filter->apply('user_can_update_avatar', true, [$user, $tid]);
if ($can instanceof Rejection) {
return json($can->getReason(), 1);
}
$dispatcher->dispatch('user.avatar.updating', [$user, $tid]);
if ($tid == 0) {
$user->avatar = 0;
$user->save();
$dispatcher->dispatch('user.avatar.updated', [$user, $tid]);
return json(trans('user.profile.avatar.success'), 0);
}
$result = Texture::find($tid);
if ($result) {
if ($result->type == 'cape') {
$texture = Texture::find($tid);
if ($texture) {
if ($texture->type == 'cape') {
return json(trans('user.profile.avatar.wrong-type'), 1);
}
$user->avatar = $tid;
$user->save();
$dispatcher->dispatch('user.avatar.updated', [$user, $tid]);
return json(trans('user.profile.avatar.success'), 0);
} else {
return json(trans('skinlib.non-existent'), 1);

View File

@ -7,6 +7,8 @@ use Parsedown;
use App\Events;
use App\Models\User;
use App\Notifications;
use App\Services\Filter;
use App\Services\Rejection;
use Illuminate\Support\Str;
use App\Mail\EmailVerification;
use Illuminate\Support\Facades\Mail;
@ -224,6 +226,19 @@ class UserControllerTest extends TestCase
Event::fake();
$user = factory(User::class)->create();
$user->changePassword('12345678');
$uid = $user->uid;
// Rejected by filter
$filter = resolve(Filter::class);
$filter->add('user_can_edit_profile', function ($can, $action, $addition) {
$this->assertEquals('nope', $action);
$this->assertEquals([], $addition);
return new Rejection('rejected');
});
$this->actingAs($user)
->postJson('/user/profile', ['action' => 'nope'])
->assertJson(['code' => 1, 'message' => 'rejected']);
$filter->remove('user_can_edit_profile');
// Invalid action
$this->actingAs($user)
@ -232,6 +247,13 @@ class UserControllerTest extends TestCase
'code' => 1,
'message' => trans('general.illegal-parameters'),
]);
Event::assertDispatched('user.profile.updating', function ($eventName, $payload) use ($uid) {
[$user, $action, $addition] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals('', $action);
$this->assertEquals([], $addition);
return true;
});
// Change nickname without `new_nickname` field
$this->postJson('/user/profile', ['action' => 'nickname'])
@ -265,7 +287,15 @@ class UserControllerTest extends TestCase
'message' => trans('user.profile.nickname.success', ['nickname' => 'nickname']),
]);
$this->assertEquals('nickname', User::find($user->uid)->nickname);
Event::assertDispatched('user.profile.updated', function ($eventName, $payload) use ($uid) {
[$user, $action, $addition] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals('nickname', $action);
$this->assertEquals(['new_nickname' => 'nickname'], $addition);
return true;
});
Event::assertDispatched(Events\UserProfileUpdated::class);
Event::fake();
// Change password without `current_password` field
$this->postJson('/user/profile', ['action' => 'password'])
@ -318,10 +348,21 @@ class UserControllerTest extends TestCase
'code' => 0,
'message' => trans('user.profile.password.success'),
]);
Event::assertDispatched('user.profile.updated', function ($eventName, $payload) use ($uid) {
[$user, $action, $addition] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals('password', $action);
$this->assertEquals([
'current_password' => '12345678',
'new_password' => '87654321',
], $addition);
return true;
});
Event::assertDispatched(Events\EncryptUserPassword::class);
$this->assertTrue(User::find($user->uid)->verifyPassword('87654321'));
// After changed password, user should re-login.
$this->assertGuest();
Event::fake();
$user = User::find($user->uid);
// Change email without `new_email` field
@ -381,10 +422,21 @@ class UserControllerTest extends TestCase
'code' => 0,
'message' => trans('user.profile.email.success'),
]);
Event::assertDispatched('user.profile.updated', function ($eventName, $payload) use ($uid) {
[$user, $action, $addition] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals('email', $action);
$this->assertEquals([
'new_email' => 'a@b.c',
'password' => '87654321',
], $addition);
return true;
});
$this->assertEquals('a@b.c', User::find($user->uid)->email);
$this->assertEquals(0, User::find($user->uid)->verified);
// After changed email, user should re-login.
$this->assertGuest();
Event::fake();
$user = User::find($user->uid);
$user->verified = true;
@ -426,6 +478,14 @@ class UserControllerTest extends TestCase
'code' => 0,
'message' => trans('user.profile.delete.success'),
]);
Event::assertDispatched('user.deleting', function ($eventName, $payload) use ($uid) {
$this->assertEquals($uid, $payload[0]->uid);
return true;
});
Event::assertDispatched('user.deleted', function ($eventName, $payload) use ($uid) {
$this->assertEquals($uid, $payload[0]->uid);
return true;
});
$this->assertNull(User::find($user->uid));
// Administrator cannot be deleted
@ -442,6 +502,7 @@ class UserControllerTest extends TestCase
public function testSetAvatar()
{
$user = factory(User::class)->create();
$uid = $user->uid;
$steve = factory(\App\Models\Texture::class)->create();
$cape = factory(\App\Models\Texture::class, 'cape')->create();
@ -457,9 +518,7 @@ class UserControllerTest extends TestCase
// Texture cannot be found
$this->actingAs($user)
->postJson('/user/profile/avatar', [
'tid' => -1,
])
->postJson('/user/profile/avatar', ['tid' => -1])
->assertJson([
'code' => 1,
'message' => trans('skinlib.non-existent'),
@ -467,29 +526,65 @@ class UserControllerTest extends TestCase
// Use cape
$this->actingAs($user)
->postJson('/user/profile/avatar', [
'tid' => $cape->tid,
])
->postJson('/user/profile/avatar', ['tid' => $cape->tid])
->assertJson([
'code' => 1,
'message' => trans('user.profile.avatar.wrong-type'),
]);
// Success
Event::fake();
$this->actingAs($user)
->postJson('/user/profile/avatar', [
'tid' => $steve->tid,
])
->postJson('/user/profile/avatar', ['tid' => $steve->tid])
->assertJson([
'code' => 0,
'message' => trans('user.profile.avatar.success'),
]);
$this->assertEquals($steve->tid, User::find($user->uid)->avatar);
Event::assertDispatched(
'user.avatar.updating',
function ($eventName, $payload) use ($uid, $steve) {
[$user, $tid] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals($steve->tid, $tid);
return true;
}
);
Event::assertDispatched(
'user.avatar.updated',
function ($eventName, $payload) use ($uid, $steve) {
[$user, $tid] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals($steve->tid, $tid);
return true;
}
);
// Reset avatar
Event::fake();
$this->postJson('/user/profile/avatar', ['tid' => 0])
->assertJson(['code' => 0]);
$this->assertEquals(0, User::find($user->uid)->avatar);
Event::assertDispatched(
'user.avatar.updated',
function ($eventName, $payload) use ($uid) {
[$user, $tid] = $payload;
$this->assertEquals($uid, $user->uid);
$this->assertEquals(0, $tid);
return true;
}
);
// Rejected by filter
$filter = resolve(Filter::class);
$filter->add('user_can_update_avatar', function ($can, $user, $tid) use ($uid, $steve) {
$this->assertEquals($uid, $user->uid);
$this->assertEquals($steve->tid, $tid);
return new Rejection('rejected');
});
$this->actingAs($user)
->postJson('/user/profile/avatar', ['tid' => $steve->tid])
->assertJson(['code' => 1, 'message' => 'rejected']);
}
public function testReadNotification()