mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-12-29 16:33:17 +00:00
commit
4412a6b5dd
4 changed files with 215 additions and 16 deletions
|
@ -18,6 +18,8 @@ use App\{
|
||||||
Status,
|
Status,
|
||||||
User
|
User
|
||||||
};
|
};
|
||||||
|
use App\Models\Conversation;
|
||||||
|
use App\Models\RemoteReport;
|
||||||
use App\Services\AccountService;
|
use App\Services\AccountService;
|
||||||
use App\Services\AdminStatsService;
|
use App\Services\AdminStatsService;
|
||||||
use App\Services\ConfigCacheService;
|
use App\Services\ConfigCacheService;
|
||||||
|
@ -25,10 +27,14 @@ use App\Services\InstanceService;
|
||||||
use App\Services\ModLogService;
|
use App\Services\ModLogService;
|
||||||
use App\Services\SnowflakeService;
|
use App\Services\SnowflakeService;
|
||||||
use App\Services\StatusService;
|
use App\Services\StatusService;
|
||||||
|
use App\Services\PublicTimelineService;
|
||||||
use App\Services\NetworkTimelineService;
|
use App\Services\NetworkTimelineService;
|
||||||
use App\Services\NotificationService;
|
use App\Services\NotificationService;
|
||||||
use App\Http\Resources\AdminInstance;
|
use App\Http\Resources\AdminInstance;
|
||||||
use App\Http\Resources\AdminUser;
|
use App\Http\Resources\AdminUser;
|
||||||
|
use App\Jobs\DeletePipeline\DeleteAccountPipeline;
|
||||||
|
use App\Jobs\DeletePipeline\DeleteRemoteProfilePipeline;
|
||||||
|
use App\Jobs\DeletePipeline\DeleteRemoteStatusPipeline;
|
||||||
|
|
||||||
class AdminApiController extends Controller
|
class AdminApiController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -93,7 +99,7 @@ class AdminApiController extends Controller
|
||||||
abort_unless($request->user()->is_admin == 1, 404);
|
abort_unless($request->user()->is_admin == 1, 404);
|
||||||
|
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'action' => 'required|in:dismiss,approve,dismiss-all,approve-all',
|
'action' => 'required|in:dismiss,approve,dismiss-all,approve-all,delete-post,delete-account',
|
||||||
'id' => 'required'
|
'id' => 'required'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -105,14 +111,53 @@ class AdminApiController extends Controller
|
||||||
$now = now();
|
$now = now();
|
||||||
$res = ['status' => 'success'];
|
$res = ['status' => 'success'];
|
||||||
$meta = json_decode($appeal->meta);
|
$meta = json_decode($appeal->meta);
|
||||||
|
$user = $appeal->user;
|
||||||
|
$profile = $user->profile;
|
||||||
|
|
||||||
if($action == 'dismiss') {
|
if($action == 'dismiss') {
|
||||||
$appeal->is_spam = true;
|
$appeal->is_spam = true;
|
||||||
$appeal->appeal_handled_at = $now;
|
$appeal->appeal_handled_at = $now;
|
||||||
$appeal->save();
|
$appeal->save();
|
||||||
|
|
||||||
Cache::forget('pf:bouncer_v0:exemption_by_pid:' . $appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:exemption_by_pid:' . $profile->id);
|
||||||
Cache::forget('pf:bouncer_v0:recent_by_pid:' . $appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:recent_by_pid:' . $profile->id);
|
||||||
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($action == 'delete-post') {
|
||||||
|
$appeal->appeal_handled_at = now();
|
||||||
|
$appeal->is_spam = true;
|
||||||
|
$appeal->save();
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($appeal->status->id)
|
||||||
|
->objectType('App\Status::class')
|
||||||
|
->user($request->user())
|
||||||
|
->action('admin.status.delete')
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
PublicTimelineService::deleteByProfileId($profile->id);
|
||||||
|
StatusDelete::dispatch($appeal->status)->onQueue('high');
|
||||||
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($action == 'delete-account') {
|
||||||
|
abort_if($user->is_admin, 400, 'Cannot delete an admin account.');
|
||||||
|
$appeal->appeal_handled_at = now();
|
||||||
|
$appeal->is_spam = true;
|
||||||
|
$appeal->save();
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($profile->id)
|
||||||
|
->objectType('App\User::class')
|
||||||
|
->user($request->user())
|
||||||
|
->action('admin.user.delete')
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
PublicTimelineService::deleteByProfileId($profile->id);
|
||||||
|
DeleteAccountPipeline::dispatch($appeal->user)->onQueue('high');
|
||||||
Cache::forget('admin-dash:reports:spam-count');
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
@ -405,6 +450,9 @@ class AdminApiController extends Controller
|
||||||
{
|
{
|
||||||
abort_if(!$request->user(), 404);
|
abort_if(!$request->user(), 404);
|
||||||
abort_unless($request->user()->is_admin == 1, 404);
|
abort_unless($request->user()->is_admin == 1, 404);
|
||||||
|
$this->validate($request, [
|
||||||
|
'sort' => 'sometimes|in:asc,desc',
|
||||||
|
]);
|
||||||
$q = $request->input('q');
|
$q = $request->input('q');
|
||||||
$sort = $request->input('sort', 'desc') === 'asc' ? 'asc' : 'desc';
|
$sort = $request->input('sort', 'desc') === 'asc' ? 'asc' : 'desc';
|
||||||
$res = User::whereNull('status')
|
$res = User::whereNull('status')
|
||||||
|
@ -422,17 +470,29 @@ class AdminApiController extends Controller
|
||||||
abort_unless($request->user()->is_admin == 1, 404);
|
abort_unless($request->user()->is_admin == 1, 404);
|
||||||
|
|
||||||
$id = $request->input('user_id');
|
$id = $request->input('user_id');
|
||||||
$user = User::findOrFail($id);
|
$key = 'pf-admin-api:getUser:byId:' . $id;
|
||||||
$profile = $user->profile;
|
if($request->has('refresh')) {
|
||||||
$account = AccountService::get($user->profile_id, true);
|
Cache::forget($key);
|
||||||
return (new AdminUser($user))->additional(['meta' => [
|
}
|
||||||
'account' => $account,
|
return Cache::remember($key, 86400, function() use($id) {
|
||||||
'moderation' => [
|
$user = User::findOrFail($id);
|
||||||
'unlisted' => (bool) $profile->unlisted,
|
$profile = $user->profile;
|
||||||
'cw' => (bool) $profile->cw,
|
$account = AccountService::get($user->profile_id, true);
|
||||||
'no_autolink' => (bool) $profile->no_autolink
|
$res = (new AdminUser($user))->additional(['meta' => [
|
||||||
]
|
'cached_at' => str_replace('+00:00', 'Z', now()->format(DATE_RFC3339_EXTENDED)),
|
||||||
]]);
|
'account' => $account,
|
||||||
|
'dms_sent' => Conversation::whereFromId($profile->id)->count(),
|
||||||
|
'report_count' => Report::where('object_id', $profile->id)->orWhere('reported_profile_id', $profile->id)->count(),
|
||||||
|
'remote_report_count' => RemoteReport::whereAccountId($profile->id)->count(),
|
||||||
|
'moderation' => [
|
||||||
|
'unlisted' => (bool) $profile->unlisted,
|
||||||
|
'cw' => (bool) $profile->cw,
|
||||||
|
'no_autolink' => (bool) $profile->no_autolink
|
||||||
|
]
|
||||||
|
]]);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function userAdminAction(Request $request)
|
public function userAdminAction(Request $request)
|
||||||
|
@ -442,7 +502,7 @@ class AdminApiController extends Controller
|
||||||
|
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'id' => 'required',
|
'id' => 'required',
|
||||||
'action' => 'required|in:unlisted,cw,no_autolink,refresh_stats,verify_email',
|
'action' => 'required|in:unlisted,cw,no_autolink,refresh_stats,verify_email,delete',
|
||||||
'value' => 'sometimes'
|
'value' => 'sometimes'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -453,7 +513,59 @@ class AdminApiController extends Controller
|
||||||
|
|
||||||
abort_if($user->is_admin == true && $action !== 'refresh_stats', 400, 'Cannot moderate admin accounts');
|
abort_if($user->is_admin == true && $action !== 'refresh_stats', 400, 'Cannot moderate admin accounts');
|
||||||
|
|
||||||
if($action === 'refresh_stats') {
|
if($action === 'delete') {
|
||||||
|
if(config('pixelfed.account_deletion') == false) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort_if($user->is_admin, 400, 'Cannot delete an admin account.');
|
||||||
|
|
||||||
|
$ts = now()->addMonth();
|
||||||
|
|
||||||
|
$user->status = 'delete';
|
||||||
|
$user->delete_after = $ts;
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
$profile->status = 'delete';
|
||||||
|
$profile->delete_after = $ts;
|
||||||
|
$profile->save();
|
||||||
|
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($profile->id)
|
||||||
|
->objectType('App\Profile::class')
|
||||||
|
->user($request->user())
|
||||||
|
->action('admin.user.delete')
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
|
||||||
|
PublicTimelineService::deleteByProfileId($profile->id);
|
||||||
|
NetworkTimelineService::deleteByProfileId($profile->id);
|
||||||
|
|
||||||
|
if($profile->user_id) {
|
||||||
|
DB::table('oauth_access_tokens')->whereUserId($user->id)->delete();
|
||||||
|
DB::table('oauth_auth_codes')->whereUserId($user->id)->delete();
|
||||||
|
$user->email = $user->id;
|
||||||
|
$user->password = '';
|
||||||
|
$user->status = 'delete';
|
||||||
|
$user->save();
|
||||||
|
$profile->status = 'delete';
|
||||||
|
$profile->delete_after = now()->addMonth();
|
||||||
|
$profile->save();
|
||||||
|
AccountService::del($profile->id);
|
||||||
|
DeleteAccountPipeline::dispatch($user)->onQueue('high');
|
||||||
|
} else {
|
||||||
|
$profile->status = 'delete';
|
||||||
|
$profile->delete_after = now()->addMonth();
|
||||||
|
$profile->save();
|
||||||
|
AccountService::del($profile->id);
|
||||||
|
DeleteRemoteProfilePipeline::dispatch($profile)->onQueue('high');
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'status' => 200,
|
||||||
|
'msg' => 'deleted',
|
||||||
|
];
|
||||||
|
} else if($action === 'refresh_stats') {
|
||||||
$profile->following_count = DB::table('followers')->whereProfileId($user->profile_id)->count();
|
$profile->following_count = DB::table('followers')->whereProfileId($user->profile_id)->count();
|
||||||
$profile->followers_count = DB::table('followers')->whereFollowingId($user->profile_id)->count();
|
$profile->followers_count = DB::table('followers')->whereFollowingId($user->profile_id)->count();
|
||||||
$statusCount = Status::whereProfileId($user->profile_id)
|
$statusCount = Status::whereProfileId($user->profile_id)
|
||||||
|
@ -479,6 +591,51 @@ class AdminApiController extends Controller
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
} else if($action === 'unlisted') {
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($profile->id)
|
||||||
|
->objectType('App\Profile::class')
|
||||||
|
->user($request->user())
|
||||||
|
->action('admin.user.moderate')
|
||||||
|
->metadata([
|
||||||
|
'action' => $action,
|
||||||
|
'message' => 'Success!'
|
||||||
|
])
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
$profile->unlisted = !$profile->unlisted;
|
||||||
|
$profile->save();
|
||||||
|
} else if($action === 'cw') {
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($profile->id)
|
||||||
|
->objectType('App\Profile::class')
|
||||||
|
->user($request->user())
|
||||||
|
->action('admin.user.moderate')
|
||||||
|
->metadata([
|
||||||
|
'action' => $action,
|
||||||
|
'message' => 'Success!'
|
||||||
|
])
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
$profile->cw = !$profile->cw;
|
||||||
|
$profile->save();
|
||||||
|
} else if($action === 'no_autolink') {
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($profile->id)
|
||||||
|
->objectType('App\Profile::class')
|
||||||
|
->user($request->user())
|
||||||
|
->action('admin.user.moderate')
|
||||||
|
->metadata([
|
||||||
|
'action' => $action,
|
||||||
|
'message' => 'Success!'
|
||||||
|
])
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
$profile->no_autolink = !$profile->no_autolink;
|
||||||
|
$profile->save();
|
||||||
} else {
|
} else {
|
||||||
$profile->{$action} = filter_var($request->input('value'), FILTER_VALIDATE_BOOLEAN);
|
$profile->{$action} = filter_var($request->input('value'), FILTER_VALIDATE_BOOLEAN);
|
||||||
$profile->save();
|
$profile->save();
|
||||||
|
|
|
@ -23,9 +23,11 @@ class AdminUser extends JsonResource
|
||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'username' => $this->username,
|
'username' => $this->username,
|
||||||
'is_admin' => (bool) $this->is_admin,
|
'is_admin' => (bool) $this->is_admin,
|
||||||
|
'email' => $this->email,
|
||||||
'email_verified_at' => $this->email_verified_at,
|
'email_verified_at' => $this->email_verified_at,
|
||||||
'two_factor_enabled' => (bool) $this->{'2fa_enabled'},
|
'two_factor_enabled' => (bool) $this->{'2fa_enabled'},
|
||||||
'register_source' => $this->register_source,
|
'register_source' => $this->register_source,
|
||||||
|
'app_register_ip' => $this->app_register_ip,
|
||||||
'last_active_at' => $this->last_active_at,
|
'last_active_at' => $this->last_active_at,
|
||||||
'created_at' => $this->created_at,
|
'created_at' => $this->created_at,
|
||||||
];
|
];
|
||||||
|
|
|
@ -72,6 +72,26 @@ class NetworkTimelineService
|
||||||
return Redis::zcard(self::CACHE_KEY);
|
return Redis::zcard(self::CACHE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function deleteByProfileId($profileId)
|
||||||
|
{
|
||||||
|
$res = Redis::zrange(self::CACHE_KEY, 0, '-1');
|
||||||
|
if(!$res) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach($res as $postId) {
|
||||||
|
$s = StatusService::get($postId);
|
||||||
|
if(!$s) {
|
||||||
|
self::rem($postId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if($s['account']['id'] == $profileId) {
|
||||||
|
self::rem($postId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public static function warmCache($force = false, $limit = 100)
|
public static function warmCache($force = false, $limit = 100)
|
||||||
{
|
{
|
||||||
if(self::count() == 0 || $force == true) {
|
if(self::count() == 0 || $force == true) {
|
||||||
|
|
|
@ -72,6 +72,26 @@ class PublicTimelineService {
|
||||||
return Redis::zcard(self::CACHE_KEY);
|
return Redis::zcard(self::CACHE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function deleteByProfileId($profileId)
|
||||||
|
{
|
||||||
|
$res = Redis::zrange(self::CACHE_KEY, 0, '-1');
|
||||||
|
if(!$res) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach($res as $postId) {
|
||||||
|
$s = StatusService::get($postId);
|
||||||
|
if(!$s) {
|
||||||
|
self::rem($postId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if($s['account']['id'] == $profileId) {
|
||||||
|
self::rem($postId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public static function warmCache($force = false, $limit = 100)
|
public static function warmCache($force = false, $limit = 100)
|
||||||
{
|
{
|
||||||
if(self::count() == 0 || $force == true) {
|
if(self::count() == 0 || $force == true) {
|
||||||
|
|
Loading…
Reference in a new issue