Merge pull request #4500 from pixelfed/staging

Staging
This commit is contained in:
daniel 2023-06-22 06:48:23 -06:00 committed by GitHub
commit 4412a6b5dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 215 additions and 16 deletions

View file

@ -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();

View file

@ -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,
]; ];

View file

@ -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) {

View file

@ -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) {