mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-26 08:13:16 +00:00
commit
e4f33e823d
4 changed files with 1763 additions and 1579 deletions
|
@ -2,38 +2,31 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\AccountInterstitial;
|
||||||
|
use App\Http\Resources\AdminReport;
|
||||||
|
use App\Http\Resources\AdminSpamReport;
|
||||||
|
use App\Jobs\DeletePipeline\DeleteAccountPipeline;
|
||||||
|
use App\Jobs\DeletePipeline\DeleteRemoteProfilePipeline;
|
||||||
|
use App\Jobs\StatusPipeline\RemoteStatusDelete;
|
||||||
|
use App\Jobs\StatusPipeline\StatusDelete;
|
||||||
|
use App\Jobs\StoryPipeline\StoryDelete;
|
||||||
|
use App\Notification;
|
||||||
|
use App\Profile;
|
||||||
|
use App\Report;
|
||||||
|
use App\Services\AccountService;
|
||||||
|
use App\Services\ModLogService;
|
||||||
|
use App\Services\NetworkTimelineService;
|
||||||
|
use App\Services\NotificationService;
|
||||||
|
use App\Services\PublicTimelineService;
|
||||||
|
use App\Services\StatusService;
|
||||||
|
use App\Status;
|
||||||
|
use App\Story;
|
||||||
|
use App\User;
|
||||||
use Cache;
|
use Cache;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
use App\Services\AccountService;
|
|
||||||
use App\Services\StatusService;
|
|
||||||
use App\{
|
|
||||||
AccountInterstitial,
|
|
||||||
Contact,
|
|
||||||
Hashtag,
|
|
||||||
Newsroom,
|
|
||||||
Notification,
|
|
||||||
OauthClient,
|
|
||||||
Profile,
|
|
||||||
Report,
|
|
||||||
Status,
|
|
||||||
Story,
|
|
||||||
User
|
|
||||||
};
|
|
||||||
use Illuminate\Validation\Rule;
|
|
||||||
use App\Services\StoryService;
|
|
||||||
use App\Services\ModLogService;
|
|
||||||
use App\Jobs\DeletePipeline\DeleteAccountPipeline;
|
|
||||||
use App\Jobs\DeletePipeline\DeleteRemoteProfilePipeline;
|
|
||||||
use App\Jobs\StatusPipeline\StatusDelete;
|
|
||||||
use App\Jobs\StatusPipeline\RemoteStatusDelete;
|
|
||||||
use App\Http\Resources\AdminReport;
|
|
||||||
use App\Http\Resources\AdminSpamReport;
|
|
||||||
use App\Services\NotificationService;
|
|
||||||
use App\Services\PublicTimelineService;
|
|
||||||
use App\Services\NetworkTimelineService;
|
|
||||||
|
|
||||||
trait AdminReportController
|
trait AdminReportController
|
||||||
{
|
{
|
||||||
|
@ -53,7 +46,7 @@ trait AdminReportController
|
||||||
$mailVerifications = Redis::scard('email:manual');
|
$mailVerifications = Redis::scard('email:manual');
|
||||||
|
|
||||||
if ($filter == 'open' && $page == 1) {
|
if ($filter == 'open' && $page == 1) {
|
||||||
$reports = Cache::remember('admin-dash:reports:list-cache', 300, function() use($page, $filter) {
|
$reports = Cache::remember('admin-dash:reports:list-cache', 300, function () use ($filter) {
|
||||||
return Report::whereHas('status')
|
return Report::whereHas('status')
|
||||||
->whereHas('reportedUser')
|
->whereHas('reportedUser')
|
||||||
->whereHas('reporter')
|
->whereHas('reporter')
|
||||||
|
@ -87,6 +80,7 @@ trait AdminReportController
|
||||||
if ($request->has('ref') && $request->input('ref') == 'email') {
|
if ($request->has('ref') && $request->input('ref') == 'email') {
|
||||||
return redirect('/i/admin/reports?tab=report&id='.$report->id);
|
return redirect('/i/admin/reports?tab=report&id='.$report->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('admin.reports.show', compact('report'));
|
return view('admin.reports.show', compact('report'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +90,7 @@ trait AdminReportController
|
||||||
->whereNull('appeal_handled_at')
|
->whereNull('appeal_handled_at')
|
||||||
->latest()
|
->latest()
|
||||||
->paginate(6);
|
->paginate(6);
|
||||||
|
|
||||||
return view('admin.reports.appeals', compact('appeals'));
|
return view('admin.reports.appeals', compact('appeals'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,13 +100,14 @@ trait AdminReportController
|
||||||
->whereNull('appeal_handled_at')
|
->whereNull('appeal_handled_at')
|
||||||
->findOrFail($id);
|
->findOrFail($id);
|
||||||
$meta = json_decode($appeal->meta);
|
$meta = json_decode($appeal->meta);
|
||||||
|
|
||||||
return view('admin.reports.show_appeal', compact('appeal', 'meta'));
|
return view('admin.reports.show_appeal', compact('appeal', 'meta'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function spam(Request $request)
|
public function spam(Request $request)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'tab' => 'sometimes|in:home,not-spam,spam,settings,custom,exemptions'
|
'tab' => 'sometimes|in:home,not-spam,spam,settings,custom,exemptions',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tab = $request->input('tab', 'home');
|
$tab = $request->input('tab', 'home');
|
||||||
|
@ -143,6 +139,7 @@ trait AdminReportController
|
||||||
if (config('database.default') != 'mysql') {
|
if (config('database.default') != 'mysql') {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AccountInterstitial::selectRaw('*, count(id) as counter')
|
return AccountInterstitial::selectRaw('*, count(id) as counter')
|
||||||
->whereType('post.autospam')
|
->whereType('post.autospam')
|
||||||
->groupBy('user_id')
|
->groupBy('user_id')
|
||||||
|
@ -152,11 +149,11 @@ trait AdminReportController
|
||||||
|
|
||||||
$avgOpen = Cache::remember('admin-dash:reports:spam-count:avgopen', 43200, function () {
|
$avgOpen = Cache::remember('admin-dash:reports:spam-count:avgopen', 43200, function () {
|
||||||
if (config('database.default') != 'mysql') {
|
if (config('database.default') != 'mysql') {
|
||||||
return "0";
|
return '0';
|
||||||
}
|
}
|
||||||
$seconds = AccountInterstitial::selectRaw('DATE(created_at) AS start_date, AVG(TIME_TO_SEC(TIMEDIFF(appeal_handled_at, created_at))) AS timediff')->whereType('post.autospam')->whereNotNull('appeal_handled_at')->where('created_at', '>', now()->subMonth())->get();
|
$seconds = AccountInterstitial::selectRaw('DATE(created_at) AS start_date, AVG(TIME_TO_SEC(TIMEDIFF(appeal_handled_at, created_at))) AS timediff')->whereType('post.autospam')->whereNotNull('appeal_handled_at')->where('created_at', '>', now()->subMonth())->get();
|
||||||
if (! $seconds) {
|
if (! $seconds) {
|
||||||
return "0";
|
return '0';
|
||||||
}
|
}
|
||||||
$mins = floor($seconds->avg('timediff') / 60);
|
$mins = floor($seconds->avg('timediff') / 60);
|
||||||
|
|
||||||
|
@ -170,7 +167,7 @@ trait AdminReportController
|
||||||
|
|
||||||
return floor($mins / 60 / 24).' day(s)';
|
return floor($mins / 60 / 24).' day(s)';
|
||||||
});
|
});
|
||||||
$avgCount = $totalCount && $avg ? floor($totalCount / $avg) : "0";
|
$avgCount = $totalCount && $avg ? floor($totalCount / $avg) : '0';
|
||||||
|
|
||||||
if (in_array($tab, ['home', 'spam', 'not-spam'])) {
|
if (in_array($tab, ['home', 'spam', 'not-spam'])) {
|
||||||
$appeals = AccountInterstitial::whereType('post.autospam')
|
$appeals = AccountInterstitial::whereType('post.autospam')
|
||||||
|
@ -194,18 +191,20 @@ trait AdminReportController
|
||||||
$appeals = $appeals->appends(['tab' => $tab]);
|
$appeals = $appeals->appends(['tab' => $tab]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$appeals = new class {
|
$appeals = new class
|
||||||
public function count() {
|
{
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render()
|
||||||
return;
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return view('admin.reports.spam', compact('tab', 'appeals', 'openCount', 'monthlyCount', 'totalCount', 'avgCount', 'avgOpen', 'uncategorized'));
|
return view('admin.reports.spam', compact('tab', 'appeals', 'openCount', 'monthlyCount', 'totalCount', 'avgCount', 'avgOpen', 'uncategorized'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +216,7 @@ trait AdminReportController
|
||||||
return redirect('/i/admin/reports?tab=autospam&id='.$appeal->id);
|
return redirect('/i/admin/reports?tab=autospam&id='.$appeal->id);
|
||||||
}
|
}
|
||||||
$meta = json_decode($appeal->meta);
|
$meta = json_decode($appeal->meta);
|
||||||
|
|
||||||
return view('admin.reports.show_spam', compact('appeal', 'meta'));
|
return view('admin.reports.show_spam', compact('appeal', 'meta'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,13 +255,14 @@ trait AdminReportController
|
||||||
});
|
});
|
||||||
|
|
||||||
Cache::forget('admin-dash:reports:spam-sync');
|
Cache::forget('admin-dash:reports:spam-sync');
|
||||||
|
|
||||||
return redirect('/i/admin/reports/autospam');
|
return redirect('/i/admin/reports/autospam');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateSpam(Request $request, $id)
|
public function updateSpam(Request $request, $id)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'action' => 'required|in:dismiss,approve,dismiss-all,approve-all,delete-account,mark-spammer'
|
'action' => 'required|in:dismiss,approve,dismiss-all,approve-all,delete-account,mark-spammer',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$action = $request->input('action');
|
$action = $request->input('action');
|
||||||
|
@ -307,6 +308,7 @@ trait AdminReportController
|
||||||
|
|
||||||
Cache::forget('profiles:private');
|
Cache::forget('profiles:private');
|
||||||
DeleteAccountPipeline::dispatch($user);
|
DeleteAccountPipeline::dispatch($user);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,6 +320,7 @@ trait AdminReportController
|
||||||
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('admin-dash:reports:spam-count');
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,6 +333,7 @@ trait AdminReportController
|
||||||
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('admin-dash:reports:spam-count');
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,6 +359,7 @@ trait AdminReportController
|
||||||
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('admin-dash:reports:spam-count');
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +375,7 @@ trait AdminReportController
|
||||||
$pro->update([
|
$pro->update([
|
||||||
'unlisted' => true,
|
'unlisted' => true,
|
||||||
'cw' => true,
|
'cw' => true,
|
||||||
'no_autolink' => true
|
'no_autolink' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Status::whereProfileId($pro->id)
|
Status::whereProfileId($pro->id)
|
||||||
|
@ -386,6 +391,7 @@ trait AdminReportController
|
||||||
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$appeal->user->profile_id);
|
||||||
Cache::forget('admin-dash:reports:spam-count');
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +417,7 @@ trait AdminReportController
|
||||||
public function updateAppeal(Request $request, $id)
|
public function updateAppeal(Request $request, $id)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'action' => 'required|in:dismiss,approve'
|
'action' => 'required|in:dismiss,approve',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$action = $request->input('action');
|
$action = $request->input('action');
|
||||||
|
@ -423,6 +429,7 @@ trait AdminReportController
|
||||||
$appeal->appeal_handled_at = now();
|
$appeal->appeal_handled_at = now();
|
||||||
$appeal->save();
|
$appeal->save();
|
||||||
Cache::forget('admin-dash:reports:ai-count');
|
Cache::forget('admin-dash:reports:ai-count');
|
||||||
|
|
||||||
return redirect('/i/admin/reports/appeals');
|
return redirect('/i/admin/reports/appeals');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +448,7 @@ trait AdminReportController
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
# code...
|
// code...
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +548,7 @@ trait AdminReportController
|
||||||
'3' => 'unlist',
|
'3' => 'unlist',
|
||||||
'4' => 'delete',
|
'4' => 'delete',
|
||||||
'5' => 'shadowban',
|
'5' => 'shadowban',
|
||||||
'6' => 'ban'
|
'6' => 'ban',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +556,7 @@ trait AdminReportController
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'action' => 'required|integer|min:1|max:10',
|
'action' => 'required|integer|min:1|max:10',
|
||||||
'ids' => 'required|array'
|
'ids' => 'required|array',
|
||||||
]);
|
]);
|
||||||
$action = $this->actionMap()[$request->input('action')];
|
$action = $this->actionMap()[$request->input('action')];
|
||||||
$ids = $request->input('ids');
|
$ids = $request->input('ids');
|
||||||
|
@ -559,8 +566,9 @@ trait AdminReportController
|
||||||
}
|
}
|
||||||
$res = [
|
$res = [
|
||||||
'message' => 'Success',
|
'message' => 'Success',
|
||||||
'code' => 200
|
'code' => 200,
|
||||||
];
|
];
|
||||||
|
|
||||||
return response()->json($res);
|
return response()->json($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,6 +592,7 @@ trait AdminReportController
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$account['email'] = $user->email;
|
$account['email'] = $user->email;
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
})
|
})
|
||||||
->filter(function ($res) {
|
->filter(function ($res) {
|
||||||
|
@ -591,6 +600,7 @@ trait AdminReportController
|
||||||
})
|
})
|
||||||
->values();
|
->values();
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('admin.reports.mail_verification', compact('reports', 'ignored'));
|
return view('admin.reports.mail_verification', compact('reports', 'ignored'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,6 +608,7 @@ trait AdminReportController
|
||||||
{
|
{
|
||||||
$id = $request->input('id');
|
$id = $request->input('id');
|
||||||
Redis::sadd('email:manual-ignored', $id);
|
Redis::sadd('email:manual-ignored', $id);
|
||||||
|
|
||||||
return redirect('/i/admin/reports');
|
return redirect('/i/admin/reports');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,12 +620,14 @@ trait AdminReportController
|
||||||
Redis::srem('email:manual-ignored', $id);
|
Redis::srem('email:manual-ignored', $id);
|
||||||
$user->email_verified_at = now();
|
$user->email_verified_at = now();
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
return redirect('/i/admin/reports');
|
return redirect('/i/admin/reports');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reportMailVerifyClearIgnored(Request $request)
|
public function reportMailVerifyClearIgnored(Request $request)
|
||||||
{
|
{
|
||||||
Redis::del('email:manual-ignored');
|
Redis::del('email:manual-ignored');
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,8 +640,9 @@ trait AdminReportController
|
||||||
'autospam' => AccountInterstitial::whereType('post.autospam')->count(),
|
'autospam' => AccountInterstitial::whereType('post.autospam')->count(),
|
||||||
'autospam_open' => AccountInterstitial::whereType('post.autospam')->whereNull(['appeal_handled_at'])->count(),
|
'autospam_open' => AccountInterstitial::whereType('post.autospam')->whereNull(['appeal_handled_at'])->count(),
|
||||||
'appeals' => AccountInterstitial::whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count(),
|
'appeals' => AccountInterstitial::whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count(),
|
||||||
'email_verification_requests' => Redis::scard('email:manual')
|
'email_verification_requests' => Redis::scard('email:manual'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $stats;
|
return $stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,6 +668,7 @@ trait AdminReportController
|
||||||
public function reportsApiGet(Request $request, $id)
|
public function reportsApiGet(Request $request, $id)
|
||||||
{
|
{
|
||||||
$report = Report::findOrFail($id);
|
$report = Report::findOrFail($id);
|
||||||
|
|
||||||
return new AdminReport($report);
|
return new AdminReport($report);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,8 +678,8 @@ trait AdminReportController
|
||||||
'object_id' => 'required',
|
'object_id' => 'required',
|
||||||
'object_type' => 'required',
|
'object_type' => 'required',
|
||||||
'id' => 'required',
|
'id' => 'required',
|
||||||
'action' => 'required|in:ignore,nsfw,unlist,private,delete',
|
'action' => 'required|in:ignore,nsfw,unlist,private,delete,delete-all',
|
||||||
'action_type' => 'required|in:post,profile'
|
'action_type' => 'required|in:post,profile,story',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$report = Report::whereObjectId($request->input('object_id'))->findOrFail($request->input('id'));
|
$report = Report::whereObjectId($request->input('object_id'))->findOrFail($request->input('id'));
|
||||||
|
@ -673,11 +688,92 @@ trait AdminReportController
|
||||||
return $this->reportsHandleProfileAction($report, $request->input('action'));
|
return $this->reportsHandleProfileAction($report, $request->input('action'));
|
||||||
} elseif ($request->input('action_type') === 'post') {
|
} elseif ($request->input('action_type') === 'post') {
|
||||||
return $this->reportsHandleStatusAction($report, $request->input('action'));
|
return $this->reportsHandleStatusAction($report, $request->input('action'));
|
||||||
|
} elseif ($request->input('action_type') === 'story') {
|
||||||
|
return $this->reportsHandleStoryAction($report, $request->input('action'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $report;
|
return $report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function reportsHandleStoryAction($report, $action)
|
||||||
|
{
|
||||||
|
switch ($action) {
|
||||||
|
case 'ignore':
|
||||||
|
Report::whereObjectId($report->object_id)
|
||||||
|
->whereObjectType($report->object_type)
|
||||||
|
->update([
|
||||||
|
'admin_seen' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [200];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
$profile = Profile::find($report->reported_profile_id);
|
||||||
|
$story = Story::whereProfileId($profile->id)->find($report->object_id);
|
||||||
|
|
||||||
|
abort_if(! $story, 400, 'Invalid or missing story');
|
||||||
|
|
||||||
|
$story->active = false;
|
||||||
|
$story->save();
|
||||||
|
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($report->object_id)
|
||||||
|
->objectType('App\Story::class')
|
||||||
|
->user(request()->user())
|
||||||
|
->action('admin.user.moderate')
|
||||||
|
->metadata([
|
||||||
|
'action' => 'delete',
|
||||||
|
'message' => 'Success!',
|
||||||
|
])
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
|
||||||
|
Report::whereObjectId($report->object_id)
|
||||||
|
->whereObjectType($report->object_type)
|
||||||
|
->update([
|
||||||
|
'admin_seen' => now(),
|
||||||
|
]);
|
||||||
|
StoryDelete::dispatch($story)->onQueue('story');
|
||||||
|
|
||||||
|
return [200];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete-all':
|
||||||
|
$profile = Profile::find($report->reported_profile_id);
|
||||||
|
$stories = Story::whereProfileId($profile->id)->whereActive(true)->get();
|
||||||
|
|
||||||
|
abort_if(! $stories || ! $stories->count(), 400, 'Invalid or missing stories');
|
||||||
|
|
||||||
|
ModLogService::boot()
|
||||||
|
->objectUid($profile->id)
|
||||||
|
->objectId($report->object_id)
|
||||||
|
->objectType('App\Story::class')
|
||||||
|
->user(request()->user())
|
||||||
|
->action('admin.user.moderate')
|
||||||
|
->metadata([
|
||||||
|
'action' => 'delete-all',
|
||||||
|
'message' => 'Success!',
|
||||||
|
])
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
|
||||||
|
Report::where('reported_profile_id', $profile->id)
|
||||||
|
->whereObjectType('App\Story')
|
||||||
|
->whereNull('admin_seen')
|
||||||
|
->update([
|
||||||
|
'admin_seen' => now(),
|
||||||
|
]);
|
||||||
|
$stories->each(function ($story) {
|
||||||
|
StoryDelete::dispatch($story)->onQueue('story');
|
||||||
|
});
|
||||||
|
|
||||||
|
return [200];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function reportsHandleProfileAction($report, $action)
|
protected function reportsHandleProfileAction($report, $action)
|
||||||
{
|
{
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
|
@ -685,8 +781,9 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -725,7 +822,7 @@ trait AdminReportController
|
||||||
->action('admin.user.moderate')
|
->action('admin.user.moderate')
|
||||||
->metadata([
|
->metadata([
|
||||||
'action' => 'cw',
|
'action' => 'cw',
|
||||||
'message' => 'Success!'
|
'message' => 'Success!',
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
@ -734,8 +831,9 @@ trait AdminReportController
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'nsfw' => true,
|
'nsfw' => true,
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -775,7 +873,7 @@ trait AdminReportController
|
||||||
->action('admin.user.moderate')
|
->action('admin.user.moderate')
|
||||||
->metadata([
|
->metadata([
|
||||||
'action' => 'unlisted',
|
'action' => 'unlisted',
|
||||||
'message' => 'Success!'
|
'message' => 'Success!',
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
@ -783,8 +881,9 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -824,7 +923,7 @@ trait AdminReportController
|
||||||
->action('admin.user.moderate')
|
->action('admin.user.moderate')
|
||||||
->metadata([
|
->metadata([
|
||||||
'action' => 'private',
|
'action' => 'private',
|
||||||
'message' => 'Success!'
|
'message' => 'Success!',
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
@ -832,8 +931,9 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -884,7 +984,7 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($profile->user_id) {
|
if ($profile->user_id) {
|
||||||
|
@ -906,6 +1006,7 @@ trait AdminReportController
|
||||||
AccountService::del($profile->id);
|
AccountService::del($profile->id);
|
||||||
DeleteRemoteProfilePipeline::dispatch($profile)->onQueue('high');
|
DeleteRemoteProfilePipeline::dispatch($profile)->onQueue('high');
|
||||||
}
|
}
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -918,8 +1019,9 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -943,7 +1045,7 @@ trait AdminReportController
|
||||||
->action('admin.status.moderate')
|
->action('admin.status.moderate')
|
||||||
->metadata([
|
->metadata([
|
||||||
'action' => 'cw',
|
'action' => 'cw',
|
||||||
'message' => 'Success!'
|
'message' => 'Success!',
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
@ -952,8 +1054,9 @@ trait AdminReportController
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'nsfw' => true,
|
'nsfw' => true,
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -980,7 +1083,7 @@ trait AdminReportController
|
||||||
->action('admin.status.moderate')
|
->action('admin.status.moderate')
|
||||||
->metadata([
|
->metadata([
|
||||||
'action' => 'private',
|
'action' => 'private',
|
||||||
'message' => 'Success!'
|
'message' => 'Success!',
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
@ -988,8 +1091,9 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1018,7 +1122,7 @@ trait AdminReportController
|
||||||
->action('admin.status.moderate')
|
->action('admin.status.moderate')
|
||||||
->metadata([
|
->metadata([
|
||||||
'action' => 'unlist',
|
'action' => 'unlist',
|
||||||
'message' => 'Success!'
|
'message' => 'Success!',
|
||||||
])
|
])
|
||||||
->accessLevel('admin')
|
->accessLevel('admin')
|
||||||
->save();
|
->save();
|
||||||
|
@ -1026,8 +1130,9 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1055,7 +1160,7 @@ trait AdminReportController
|
||||||
Report::whereObjectId($report->object_id)
|
Report::whereObjectId($report->object_id)
|
||||||
->whereObjectType($report->object_type)
|
->whereObjectType($report->object_type)
|
||||||
->update([
|
->update([
|
||||||
'admin_seen' => now()
|
'admin_seen' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [200];
|
return [200];
|
||||||
|
@ -1103,6 +1208,7 @@ trait AdminReportController
|
||||||
Cache::forget('admin-dash:reports:spam-count');
|
Cache::forget('admin-dash:reports:spam-count');
|
||||||
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$report->user->profile_id);
|
Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$report->user->profile_id);
|
||||||
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$report->user->profile_id);
|
Cache::forget('pf:bouncer_v0:recent_by_pid:'.$report->user->profile_id);
|
||||||
|
|
||||||
return [$action, $report];
|
return [$action, $report];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,7 +1256,7 @@ trait AdminReportController
|
||||||
->whereUserId($appeal->user_id)
|
->whereUserId($appeal->user_id)
|
||||||
->update([
|
->update([
|
||||||
'appeal_handled_at' => now(),
|
'appeal_handled_at' => now(),
|
||||||
'is_spam' => true
|
'is_spam' => true,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1218,6 +1324,7 @@ trait AdminReportController
|
||||||
public function reportsApiSpamGet(Request $request, $id)
|
public function reportsApiSpamGet(Request $request, $id)
|
||||||
{
|
{
|
||||||
$report = AccountInterstitial::findOrFail($id);
|
$report = AccountInterstitial::findOrFail($id);
|
||||||
|
|
||||||
return new AdminSpamReport($report);
|
return new AdminSpamReport($report);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,6 +427,31 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="viewingReport && viewingReport.object_type === 'App\\Story' && viewingReport.story" class="list-group mt-3">
|
||||||
|
<div v-if="viewingReport && viewingReport.story" class="list-group-item d-flex flex-column flex-grow-1" style="gap:0.4rem;">
|
||||||
|
<div class="d-flex justify-content-between mt-n1 text-muted small font-weight-bold">
|
||||||
|
<div>Reported Story</div>
|
||||||
|
<a class="font-weight-bold" :href="viewingReport.story.url" target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-if="viewingReport.story.type === 'photo'"
|
||||||
|
:src="viewingReport.story.media_src"
|
||||||
|
height="140"
|
||||||
|
class="rounded"
|
||||||
|
style="object-fit: cover;"
|
||||||
|
onerror="this.src='/storage/no-preview.png';this.error=null;" />
|
||||||
|
|
||||||
|
<video
|
||||||
|
v-else-if="viewingReport.story.type === 'video'"
|
||||||
|
height="140"
|
||||||
|
controls
|
||||||
|
:src="viewingReport.story.media_src"
|
||||||
|
onerror="this.src='/storage/no-preview.png';this.onerror=null;"
|
||||||
|
></video>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="viewingReport && viewingReport.admin_seen_at === null" class="mt-4">
|
<div v-if="viewingReport && viewingReport.admin_seen_at === null" class="mt-4">
|
||||||
<div v-if="viewingReport && viewingReport.object_type === 'App\\Profile'">
|
<div v-if="viewingReport && viewingReport.object_type === 'App\\Profile'">
|
||||||
<button class="btn btn-dark btn-block rounded-pill" @click="handleAction('profile', 'ignore')">Ignore Report</button>
|
<button class="btn btn-dark btn-block rounded-pill" @click="handleAction('profile', 'ignore')">Ignore Report</button>
|
||||||
|
@ -454,7 +479,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="viewingReport && viewingReport.object_type === 'App\\Status'">
|
<div v-else-if="viewingReport && viewingReport.object_type === 'App\\Status'">
|
||||||
<button class="btn btn-dark btn-block rounded-pill" @click="handleAction('post', 'ignore')">Ignore Report</button>
|
<button class="btn btn-dark btn-block rounded-pill" @click="handleAction('post', 'ignore')">Ignore Report</button>
|
||||||
<hr v-if="viewingReport && viewingReport.reported && !viewingReport.reported.is_admin" class="mt-3 mb-1">
|
<hr v-if="viewingReport && viewingReport.reported && !viewingReport.reported.is_admin" class="mt-3 mb-1">
|
||||||
<div
|
<div
|
||||||
|
@ -481,6 +506,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="viewingReport && viewingReport.object_type === 'App\\Story'">
|
||||||
|
<button class="btn btn-dark btn-block rounded-pill" @click="handleAction('story', 'ignore')">Ignore Report</button>
|
||||||
|
<hr v-if="viewingReport && viewingReport.reported && !viewingReport.reported.is_admin" class="mt-3 mb-1">
|
||||||
|
<div v-if="viewingReport && viewingReport.reported && !viewingReport.reported.is_admin">
|
||||||
|
<div class="d-flex flex-row mt-2" style="gap:0.3rem;">
|
||||||
|
<button class="btn btn-danger btn-block rounded-pill mt-0" @click="handleAction('story', 'delete')">Delete Story</button>
|
||||||
|
<button class="btn btn-outline-danger btn-block rounded-pill mt-0" @click="handleAction('story', 'delete-all')">Delete All Stories</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="viewingReport && viewingReport.reported && !viewingReport.reported.is_admin">
|
||||||
|
<hr class="my-2">
|
||||||
|
<div class="d-flex flex-row mt-2" style="gap:0.3rem;">
|
||||||
|
<button class="btn btn-outline-danger btn-sm btn-block rounded-pill mt-0" @click="handleAction('profile', 'delete')">Delete Account</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
|
@ -707,6 +750,9 @@
|
||||||
case 'App\\Status':
|
case 'App\\Status':
|
||||||
return `${report.type} Post`;
|
return `${report.type} Post`;
|
||||||
break;
|
break;
|
||||||
|
case 'App\\Story':
|
||||||
|
return `${report.type} Story`;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -766,6 +812,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
|
|
||||||
axios.post('/i/admin/api/reports/handle', {
|
axios.post('/i/admin/api/reports/handle', {
|
||||||
id: this.viewingReport.id,
|
id: this.viewingReport.id,
|
||||||
object_id: this.viewingReport.object_id,
|
object_id: this.viewingReport.object_id,
|
||||||
|
@ -831,6 +878,20 @@
|
||||||
return 'Are you sure you want to delete this post?';
|
return 'Are you sure you want to delete this post?';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if(type === 'story') {
|
||||||
|
switch(action) {
|
||||||
|
case 'ignore':
|
||||||
|
return 'Are you sure you want to ignore this story report?';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
return 'Are you sure you want to delete this story?';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete-all':
|
||||||
|
return 'Are you sure you want to delete all stories by this account?';
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
@extends('site.help.partial.template', ['breadcrumb'=>'Email Confirmation Issues'])
|
||||||
|
|
||||||
|
@section('section')
|
||||||
|
<div class="title">
|
||||||
|
<h3 class="font-weight-bold">Email Confirmation Issues</h3>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<p>If you have been redirected to this page, it may be due to one of the following reasons:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The email confirmation link has already been used.</li>
|
||||||
|
<li>The email confirmation link may have expired, they are only valid for 24 hours.</li>
|
||||||
|
<li>You cannot confirm an email for another account while logged in to a different account. Try logging out, or use a different browser to open the email confirmation link.</li>
|
||||||
|
<li>The account the associated email belongs to may have been deleted, or the account may have changed the email address.</li>
|
||||||
|
</ul>
|
||||||
|
@endsection
|
|
@ -307,7 +307,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
Route::view('instance-max-users-limit', 'site.help.instance-max-users')->name('help.instance-max-users-limit');
|
Route::view('instance-max-users-limit', 'site.help.instance-max-users')->name('help.instance-max-users-limit');
|
||||||
Route::view('import', 'site.help.import')->name('help.import');
|
Route::view('import', 'site.help.import')->name('help.import');
|
||||||
Route::view('parental-controls', 'site.help.parental-controls');
|
Route::view('parental-controls', 'site.help.parental-controls');
|
||||||
// Route::view('email-confirmation-issues', 'site.help.email-confirmation-issues')->name('help.email-confirmation-issues');
|
Route::view('email-confirmation-issues', 'site.help.email-confirmation-issues')->name('help.email-confirmation-issues');
|
||||||
Route::view('curated-onboarding', 'site.help.curated-onboarding')->name('help.curated-onboarding');
|
Route::view('curated-onboarding', 'site.help.curated-onboarding')->name('help.curated-onboarding');
|
||||||
});
|
});
|
||||||
Route::get('newsroom/{year}/{month}/{slug}', 'NewsroomController@show');
|
Route::get('newsroom/{year}/{month}/{slug}', 'NewsroomController@show');
|
||||||
|
|
Loading…
Reference in a new issue