Skip to content

Commit 9038ff6

Browse files
imorlandStyleCIBot
andauthored
[suspend][core] [1.x] fix: suspended users can remove avatar (#3998)
* fix: suspended users can remove avatar * Apply fixes from StyleCI --------- Co-authored-by: StyleCI Bot <bot@styleci.io>
1 parent f8c30c9 commit 9038ff6

File tree

4 files changed

+126
-3
lines changed

4 files changed

+126
-3
lines changed

extensions/suspend/extend.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Flarum\Suspend\Notification\UserUnsuspendedBlueprint;
2020
use Flarum\Suspend\Query\SuspendedFilterGambit;
2121
use Flarum\Suspend\RevokeAccessFromSuspendedUsers;
22+
use Flarum\User\Event\AvatarDeleting;
2223
use Flarum\User\Event\Saving;
2324
use Flarum\User\Filter\UserFilterer;
2425
use Flarum\User\Search\UserSearcher;
@@ -50,7 +51,8 @@
5051
(new Extend\Event())
5152
->listen(Saving::class, Listener\SaveSuspensionToDatabase::class)
5253
->listen(Suspended::class, Listener\SendNotificationWhenUserIsSuspended::class)
53-
->listen(Unsuspended::class, Listener\SendNotificationWhenUserIsUnsuspended::class),
54+
->listen(Unsuspended::class, Listener\SendNotificationWhenUserIsUnsuspended::class)
55+
->listen(AvatarDeleting::class, Listener\PreventAvatarDeletionBySuspendedUser::class),
5456

5557
(new Extend\Policy())
5658
->modelPolicy(User::class, UserPolicy::class),
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Flarum.
5+
*
6+
* For detailed copyright and license information, please view the
7+
* LICENSE file that was distributed with this source code.
8+
*/
9+
10+
namespace Flarum\Suspend\Listener;
11+
12+
use Flarum\User\Exception\PermissionDeniedException;
13+
14+
class PreventAvatarDeletionBySuspendedUser
15+
{
16+
public function handle($event)
17+
{
18+
$actor = $event->actor;
19+
$user = $event->user;
20+
21+
if ($actor->id === $user->id && $user->suspended_until) {
22+
throw new PermissionDeniedException();
23+
}
24+
}
25+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Flarum.
5+
*
6+
* For detailed copyright and license information, please view the
7+
* LICENSE file that was distributed with this source code.
8+
*/
9+
10+
namespace Flarum\Suspend\Tests\integration\api\users;
11+
12+
use Carbon\Carbon;
13+
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
14+
use Flarum\Testing\integration\TestCase;
15+
use Psr\Http\Message\ResponseInterface;
16+
17+
class RemoveAvatarTest extends TestCase
18+
{
19+
use RetrievesAuthorizedUsers;
20+
21+
public function setUp(): void
22+
{
23+
parent::setUp();
24+
25+
$this->extension('flarum-suspend');
26+
27+
$this->prepareDatabase([
28+
'users' => [
29+
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
30+
$this->normalUser(),
31+
['id' => 3, 'username' => 'acme', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->addDay(), 'suspend_message' => 'You have been suspended.', 'suspend_reason' => 'Suspended for acme reasons.'],
32+
['id' => 4, 'username' => 'acme4', 'email' => 'acme4@machine.local', 'is_email_confirmed' => 1],
33+
['id' => 5, 'username' => 'acme5', 'email' => 'acme5@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->subDay(), 'suspend_message' => 'You have been suspended.', 'suspend_reason' => 'Suspended for acme reasons.'],
34+
],
35+
'groups' => [
36+
['id' => 5, 'name_singular' => 'can_edit_users', 'name_plural' => 'can_edit_users', 'is_hidden' => 0]
37+
],
38+
'group_user' => [
39+
['user_id' => 2, 'group_id' => 5]
40+
],
41+
'group_permission' => [
42+
['permission' => 'user.edit', 'group_id' => 5],
43+
]
44+
]);
45+
}
46+
47+
/**
48+
* @test
49+
* @dataProvider allowedToRemoveAvatar
50+
*/
51+
public function can_remove_avatar_if_allowed(?int $authenticatedAs, int $targetUserId)
52+
{
53+
$response = $this->sendRemoveAvatarRequest($authenticatedAs, $targetUserId);
54+
55+
$this->assertEquals(200, $response->getStatusCode(), $response->getBody()->getContents());
56+
}
57+
58+
/**
59+
* @test
60+
* @dataProvider notAllowedToRemoveAvatar
61+
*/
62+
public function cannot_remove_avatar_if_not_allowed(?int $authenticatedAs, int $targetUserId)
63+
{
64+
$response = $this->sendRemoveAvatarRequest($authenticatedAs, $targetUserId);
65+
66+
$this->assertEquals(403, $response->getStatusCode(), $response->getBody()->getContents());
67+
}
68+
69+
public function allowedToRemoveAvatar(): array
70+
{
71+
return [
72+
[1, 4, 'Admin can remove avatar of normal user'],
73+
[4, 4, 'Normal user can remove their own avatar'],
74+
[1, 3, 'Admin can remove avatar of suspended user'],
75+
[2, 3, 'Normal user with permission can remove avatar of suspended user'],
76+
];
77+
}
78+
79+
public function notAllowedToRemoveAvatar(): array
80+
{
81+
return [
82+
[4, 2, 'Normal user cannot remove avatar of another user'],
83+
[4, 3, 'Normal user cannot remove avatar of suspended user'],
84+
[3, 3, 'Suspended user cannot remove their own avatar'],
85+
];
86+
}
87+
88+
protected function sendRemoveAvatarRequest(?int $authenticatedAs, int $targetUserId): ResponseInterface
89+
{
90+
return $this->send(
91+
$this->request('DELETE', "/api/users/$targetUserId/avatar", [
92+
'authenticatedAs' => $authenticatedAs,
93+
])
94+
);
95+
}
96+
}

framework/core/src/User/Command/DeleteAvatarHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ public function handle(DeleteAvatar $command)
5656
$actor->assertCan('edit', $user);
5757
}
5858

59-
$this->uploader->remove($user);
60-
6159
$this->events->dispatch(
6260
new AvatarDeleting($user, $actor)
6361
);
6462

63+
$this->uploader->remove($user);
64+
6565
$user->save();
6666

6767
$this->dispatchEventsFor($user, $actor);

0 commit comments

Comments
 (0)