Skip to content

Commit

Permalink
Update mute/block logic with admin defined limits and improved filter…
Browse files Browse the repository at this point in the history
…ing to skip deleted accounts
  • Loading branch information
dansup committed Mar 1, 2023
1 parent 18940cb commit 5b879f0
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 90 deletions.
153 changes: 83 additions & 70 deletions app/Http/Controllers/AccountController.php
Expand Up @@ -17,16 +17,20 @@
EmailVerification,
Follower,
FollowRequest,
Media,
Notification,
Profile,
User,
UserFilter
UserDevice,
UserFilter,
UserSetting
};
use League\Fractal;
use League\Fractal\Serializer\ArraySerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use App\Transformer\Api\Mastodon\v1\AccountTransformer;
use App\Services\AccountService;
use App\Services\NotificationService;
use App\Services\UserFilterService;
use App\Services\RelationshipService;
use App\Jobs\FollowPipeline\FollowAcceptPipeline;
Expand All @@ -39,7 +43,8 @@ class AccountController extends Controller
'user.block',
];

const FILTER_LIMIT = 'You cannot block or mute more than 100 accounts';
const FILTER_LIMIT_MUTE_TEXT = 'You cannot mute more than ';
const FILTER_LIMIT_BLOCK_TEXT = 'You cannot block more than ';

public function __construct()
{
Expand Down Expand Up @@ -145,16 +150,17 @@ public function directMessage(Request $request, $id)
public function mute(Request $request)
{
$this->validate($request, [
'type' => 'required|alpha_dash',
'type' => 'required|string|in:user',
'item' => 'required|integer|min:1',
]);

$user = Auth::user()->profile;
$count = UserFilterService::muteCount($user->id);
abort_if($count >= 100, 422, self::FILTER_LIMIT);
$pid = $request->user()->profile_id;
$count = UserFilterService::muteCount($pid);
$maxLimit = intval(config('instance.user_filters.max_user_mutes'));
abort_if($count >= $maxLimit, 422, self::FILTER_LIMIT_MUTE_TEXT . $maxLimit . ' accounts');
if($count == 0) {
$filterCount = UserFilter::whereUserId($user->id)->count();
abort_if($filterCount >= 100, 422, self::FILTER_LIMIT);
$filterCount = UserFilter::whereUserId($pid)->count();
abort_if($filterCount >= $maxLimit, 422, self::FILTER_LIMIT_MUTE_TEXT . $maxLimit . ' accounts');
}
$type = $request->input('type');
$item = $request->input('item');
Expand All @@ -167,7 +173,7 @@ public function mute(Request $request)
switch ($type) {
case 'user':
$profile = Profile::findOrFail($item);
if ($profile->id == $user->id) {
if ($profile->id == $pid) {
return abort(403);
}
$class = get_class($profile);
Expand All @@ -177,29 +183,30 @@ public function mute(Request $request)
}

$filter = UserFilter::firstOrCreate([
'user_id' => $user->id,
'user_id' => $pid,
'filterable_id' => $filterable['id'],
'filterable_type' => $filterable['type'],
'filter_type' => 'mute',
]);

$pid = $user->id;
Cache::forget("user:filter:list:$pid");
Cache::forget("feature:discover:posts:$pid");
Cache::forget("api:local:exp:rec:$pid");
RelationshipService::refresh($pid, $profile->id);
UserFilterService::mute($pid, $filterable['id']);
$res = RelationshipService::refresh($pid, $profile->id);

return redirect()->back();
if($request->wantsJson()) {
return response()->json($res);
} else {
return redirect()->back();
}
}

public function unmute(Request $request)
{
$this->validate($request, [
'type' => 'required|alpha_dash',
'type' => 'required|string|in:user',
'item' => 'required|integer|min:1',
]);

$user = Auth::user()->profile;
$pid = $request->user()->profile_id;
$type = $request->input('type');
$item = $request->input('item');
$action = $type . '.mute';
Expand All @@ -211,7 +218,7 @@ public function unmute(Request $request)
switch ($type) {
case 'user':
$profile = Profile::findOrFail($item);
if ($profile->id == $user->id) {
if ($profile->id == $pid) {
return abort(403);
}
$class = get_class($profile);
Expand All @@ -224,24 +231,21 @@ public function unmute(Request $request)
break;
}

$filter = UserFilter::whereUserId($user->id)
$filter = UserFilter::whereUserId($pid)
->whereFilterableId($filterable['id'])
->whereFilterableType($filterable['type'])
->whereFilterType('mute')
->first();

if($filter) {
UserFilterService::unmute($pid, $filterable['id']);
$filter->delete();
}

$pid = $user->id;
Cache::forget("user:filter:list:$pid");
Cache::forget("feature:discover:posts:$pid");
Cache::forget("api:local:exp:rec:$pid");
RelationshipService::refresh($pid, $profile->id);
$res = RelationshipService::refresh($pid, $profile->id);

if($request->wantsJson()) {
return response()->json([200]);
return response()->json($res);
} else {
return redirect()->back();
}
Expand All @@ -250,16 +254,16 @@ public function unmute(Request $request)
public function block(Request $request)
{
$this->validate($request, [
'type' => 'required|alpha_dash',
'type' => 'required|string|in:user',
'item' => 'required|integer|min:1',
]);

$user = Auth::user()->profile;
$count = UserFilterService::blockCount($user->id);
abort_if($count >= 100, 422, self::FILTER_LIMIT);
$pid = $request->user()->profile_id;
$count = UserFilterService::blockCount($pid);
$maxLimit = intval(config('instance.user_filters.max_user_blocks'));
abort_if($count >= $maxLimit, 422, self::FILTER_LIMIT_BLOCK_TEXT . $maxLimit . ' accounts');
if($count == 0) {
$filterCount = UserFilter::whereUserId($user->id)->count();
abort_if($filterCount >= 100, 422, self::FILTER_LIMIT);
$filterCount = UserFilter::whereUserId($pid)->whereFilterType('block')->count();
abort_if($filterCount >= $maxLimit, 422, self::FILTER_LIMIT_BLOCK_TEXT . $maxLimit . ' accounts');
}
$type = $request->input('type');
$item = $request->input('item');
Expand All @@ -271,41 +275,49 @@ public function block(Request $request)
switch ($type) {
case 'user':
$profile = Profile::findOrFail($item);
if ($profile->id == $user->id || ($profile->user && $profile->user->is_admin == true)) {
if ($profile->id == $pid || ($profile->user && $profile->user->is_admin == true)) {
return abort(403);
}
$class = get_class($profile);
$filterable['id'] = $profile->id;
$filterable['type'] = $class;

Follower::whereProfileId($profile->id)->whereFollowingId($user->id)->delete();
Notification::whereProfileId($user->id)->whereActorId($profile->id)->delete();
Follower::whereProfileId($profile->id)->whereFollowingId($pid)->delete();
Notification::whereProfileId($pid)
->whereActorId($profile->id)
->get()
->map(function($n) use($pid) {
NotificationService::del($pid, $n['id']);
$n->forceDelete();
});
break;
}

$filter = UserFilter::firstOrCreate([
'user_id' => $user->id,
'user_id' => $pid,
'filterable_id' => $filterable['id'],
'filterable_type' => $filterable['type'],
'filter_type' => 'block',
]);

$pid = $user->id;
Cache::forget("user:filter:list:$pid");
Cache::forget("api:local:exp:rec:$pid");
RelationshipService::refresh($pid, $profile->id);
UserFilterService::block($pid, $filterable['id']);
$res = RelationshipService::refresh($pid, $profile->id);

return redirect()->back();
if($request->wantsJson()) {
return response()->json($res);
} else {
return redirect()->back();
}
}

public function unblock(Request $request)
{
$this->validate($request, [
'type' => 'required|alpha_dash',
'type' => 'required|string|in:user',
'item' => 'required|integer|min:1',
]);

$user = Auth::user()->profile;
$pid = $request->user()->profile_id;
$type = $request->input('type');
$item = $request->input('item');
$action = $type . '.block';
Expand All @@ -316,7 +328,7 @@ public function unblock(Request $request)
switch ($type) {
case 'user':
$profile = Profile::findOrFail($item);
if ($profile->id == $user->id) {
if ($profile->id == $pid) {
return abort(403);
}
$class = get_class($profile);
Expand All @@ -330,23 +342,24 @@ public function unblock(Request $request)
}


$filter = UserFilter::whereUserId($user->id)
$filter = UserFilter::whereUserId($pid)
->whereFilterableId($filterable['id'])
->whereFilterableType($filterable['type'])
->whereFilterType('block')
->first();

if($filter) {
UserFilterService::unblock($pid, $filterable['id']);
$filter->delete();
}

$pid = $user->id;
Cache::forget("user:filter:list:$pid");
Cache::forget("feature:discover:posts:$pid");
Cache::forget("api:local:exp:rec:$pid");
RelationshipService::refresh($pid, $profile->id);
$res = RelationshipService::refresh($pid, $profile->id);

return redirect()->back();
if($request->wantsJson()) {
return response()->json($res);
} else {
return redirect()->back();
}
}

public function followRequests(Request $request)
Expand Down Expand Up @@ -513,25 +526,25 @@ public function twoFactorVerify(Request $request)
}
}

protected function twoFactorBackupCheck($request, $code, User $user)
{
$backupCodes = $user->{'2fa_backup_codes'};
if($backupCodes) {
$codes = json_decode($backupCodes, true);
foreach ($codes as $c) {
if(hash_equals($c, $code)) {
$codes = array_flatten(array_diff($codes, [$code]));
$user->{'2fa_backup_codes'} = json_encode($codes);
$user->save();
$request->session()->push('2fa.session.active', true);
return true;
}
}
return false;
} else {
protected function twoFactorBackupCheck($request, $code, User $user)
{
$backupCodes = $user->{'2fa_backup_codes'};
if($backupCodes) {
$codes = json_decode($backupCodes, true);
foreach ($codes as $c) {
if(hash_equals($c, $code)) {
$codes = array_flatten(array_diff($codes, [$code]));
$user->{'2fa_backup_codes'} = json_encode($codes);
$user->save();
$request->session()->push('2fa.session.active', true);
return true;
}
}
return false;
}
}
} else {
return false;
}
}

public function accountRestored(Request $request)
{
Expand Down

0 comments on commit 5b879f0

Please sign in to comment.