diff --git a/CHANGELOG.md b/CHANGELOG.md index 99003abc..eea05762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,12 @@ - Updated DiscoverController, fixes #2009 ([b04c7170](https://github.com/pixelfed/pixelfed/commit/b04c7170)) - Updated DeleteAccountPipeline, fixes [#2016](https://github.com/pixelfed/pixelfed/issues/2016), a bug affecting account deletion. - Updated PlaceController, fixes [#2017](https://github.com/pixelfed/pixelfed/issues/2017), a postgres bug affecting country pagination in the places directory ([dd5fa3a4](https://github.com/pixelfed/pixelfed/commit/dd5fa3a4)) +- Updated confirm email blade view, remove html5 entity that doesn't display properly ([aa26fa1d](https://github.com/pixelfed/pixelfed/commit/aa26fa1d)) +- Updated ApiV1Controller, fix update_credentials endpoint ([a73fad75](https://github.com/pixelfed/pixelfed/commit/a73fad75)) +- Updated AdminUserController, add moderation method ([a4cf21ea](https://github.com/pixelfed/pixelfed/commit/a4cf21ea)) +- Updated BaseApiController, invalidate session after account deletion ([826978ce](https://github.com/pixelfed/pixelfed/commit/826978ce)) +- Updated AdminUserController, add account deletion handler ([9be19ad8](https://github.com/pixelfed/pixelfed/commit/9be19ad8)) +- ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.10.8 (2020-01-29)](https://github.com/pixelfed/pixelfed/compare/v0.10.7...v0.10.8) ### Added diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 37ccbba3..dac8078a 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -270,7 +270,6 @@ class AccountController extends Controller return redirect()->back(); } - public function unblock(Request $request) { $this->validate($request, [ @@ -362,6 +361,13 @@ class AccountController extends Controller public function sudoMode(Request $request) { + if($request->session()->has('sudoModeAttempts') && $request->session()->get('sudoModeAttempts') >= 3) { + $request->session()->pull('2fa.session.active'); + $request->session()->pull('redirectNext'); + $request->session()->pull('sudoModeAttempts'); + Auth::logout(); + return redirect(route('login')); + } return view('auth.sudo'); } @@ -373,6 +379,12 @@ class AccountController extends Controller $user = Auth::user(); $password = $request->input('password'); $next = $request->session()->get('redirectNext', '/'); + if($request->session()->has('sudoModeAttempts')) { + $count = (int) $request->session()->get('sudoModeAttempts'); + $request->session()->put('sudoModeAttempts', $count + 1); + } else { + $request->session()->put('sudoModeAttempts', 1); + } if(password_verify($password, $user->password) === true) { $request->session()->put('sudoMode', time()); return redirect($next); diff --git a/app/Http/Controllers/Admin/AdminUserController.php b/app/Http/Controllers/Admin/AdminUserController.php new file mode 100644 index 00000000..a5f19f4d --- /dev/null +++ b/app/Http/Controllers/Admin/AdminUserController.php @@ -0,0 +1,284 @@ +query('col') ?? 'id'; + $dir = $request->query('dir') ?? 'desc'; + $users = User::select('id', 'username', 'status') + ->withCount('statuses') + ->orderBy($col, $dir) + ->simplePaginate(10); + + return view('admin.users.home', compact('users')); + } + + public function userShow(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + return view('admin.users.show', compact('user', 'profile')); + } + + public function userEdit(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + return view('admin.users.edit', compact('user', 'profile')); + } + + public function userEditSubmit(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + $changed = false; + $fields = []; + + if($request->filled('name') && $request->input('name') != $user->name) { + $fields['name'] = ['old' => $user->name, 'new' => $request->input('name')]; + $user->name = $profile->name = $request->input('name'); + $changed = true; + } + if($request->filled('username') && $request->input('username') != $user->username) { + $fields['username'] = ['old' => $user->username, 'new' => $request->input('username')]; + $user->username = $profile->username = $request->input('username'); + $changed = true; + } + if($request->filled('email') && $request->input('email') != $user->email) { + if(filter_var($request->input('email'), FILTER_VALIDATE_EMAIL) == false) { + abort(500, 'Invalid email address'); + } + $fields['email'] = ['old' => $user->email, 'new' => $request->input('email')]; + $user->email = $request->input('email'); + $changed = true; + } + if($request->input('bio') != $profile->bio) { + $fields['bio'] = ['old' => $user->bio, 'new' => $request->input('bio')]; + $profile->bio = $request->input('bio'); + $changed = true; + } + if($request->input('website') != $profile->website) { + $fields['website'] = ['old' => $user->website, 'new' => $request->input('website')]; + $profile->website = $request->input('website'); + $changed = true; + } + + if($changed == true) { + ModLogService::boot() + ->objectUid($user->id) + ->objectId($user->id) + ->objectType('App\User::class') + ->user($request->user()) + ->action('admin.user.edit') + ->metadata([ + 'fields' => $fields + ]) + ->accessLevel('admin') + ->save(); + $profile->save(); + $user->save(); + } + + + return redirect('/i/admin/users/show/' . $user->id); + } + + public function userActivity(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + $logs = $user->accountLog()->orderByDesc('created_at')->paginate(10); + return view('admin.users.activity', compact('user', 'profile', 'logs')); + } + + public function userMessage(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + return view('admin.users.message', compact('user', 'profile')); + } + + public function userMessageSend(Request $request, $id) + { + $this->validate($request, [ + 'message' => 'required|string|min:5|max:500' + ]); + $user = User::findOrFail($id); + $profile = $user->profile; + $message = $request->input('message'); + Mail::to($user->email)->send(new AdminMessage($message)); + ModLogService::boot() + ->objectUid($user->id) + ->objectId($user->id) + ->objectType('App\User::class') + ->user($request->user()) + ->action('admin.user.mail') + ->metadata([ + 'message' => $message + ]) + ->accessLevel('admin') + ->save(); + return redirect('/i/admin/users/show/' . $user->id); + } + + public function userModTools(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + return view('admin.users.modtools', compact('user', 'profile')); + } + + public function userModLogs(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + $logs = ModLog::whereObjectUid($user->id) + ->orderByDesc('created_at') + ->simplePaginate(10); + return view('admin.users.modlogs', compact('user', 'profile', 'logs')); + } + + public function userModLogsMessage(Request $request, $id) + { + $this->validate($request, [ + 'message' => 'required|string|min:5|max:500' + ]); + $user = User::findOrFail($id); + $profile = $user->profile; + $msg = $request->input('message'); + ModLogService::boot() + ->objectUid($user->id) + ->objectId($user->id) + ->objectType('App\User::class') + ->user($request->user()) + ->message($msg) + ->accessLevel('admin') + ->save(); + return redirect('/i/admin/users/modlogs/' . $user->id); + } + + public function userDelete(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + return view('admin.users.delete', compact('user', 'profile')); + } + + public function userDeleteProcess(Request $request, $id) + { + $user = User::findOrFail($id); + $profile = $user->profile; + + if(config('pixelfed.account_deletion') == false) { + abort(404); + } + + if($user->is_admin == true) { + $mid = $request->user()->id; + abort_if($user->id < $mid, 403); + } + + $ts = now()->addMonth(); + $user->status = 'delete'; + $profile->status = 'delete'; + $user->delete_after = $ts; + $profile->delete_after = $ts; + $user->save(); + $profile->save(); + + ModLogService::boot() + ->objectUid($user->id) + ->objectId($user->id) + ->objectType('App\User::class') + ->user($request->user()) + ->action('admin.user.delete') + ->accessLevel('admin') + ->save(); + + Cache::forget('profiles:private'); + DeleteAccountPipeline::dispatch($user)->onQueue('high'); + + $msg = "Successfully deleted {$user->username}!"; + $request->session()->flash('status', $msg); + return redirect('/i/admin/users/list'); + } + + public function userModerate(Request $request) + { + $this->validate($request, [ + 'profile_id' => 'required|exists:profiles,id', + 'action' => 'required|in:cw,no_autolink,unlisted' + ]); + + $pid = $request->input('profile_id'); + $action = $request->input('action'); + $profile = Profile::findOrFail($pid); + + if($profile->user->is_admin == true) { + $mid = $request->user()->id; + abort_if($profile->user_id < $mid, 403); + } + + switch ($action) { + case 'cw': + $profile->cw = !$profile->cw; + $msg = "Success!"; + break; + + case 'no_autolink': + $profile->no_autolink = !$profile->no_autolink; + $msg = "Success!"; + break; + + case 'unlisted': + $profile->unlisted = !$profile->unlisted; + $msg = "Success!"; + break; + } + + $profile->save(); + + ModLogService::boot() + ->objectUid($profile->user_id) + ->objectId($profile->user_id) + ->objectType('App\User::class') + ->user($request->user()) + ->action('admin.user.moderate') + ->metadata([ + 'action' => $action, + 'message' => $msg + ]) + ->accessLevel('admin') + ->save(); + + $request->session()->flash('status', $msg); + return redirect('/i/admin/users/modtools/' . $profile->user_id); + } + + public function userModLogDelete(Request $request, $id) + { + $this->validate($request, [ + 'mid' => 'required|integer|exists:mod_logs,id' + ]); + $user = User::findOrFail($id); + $uid = $request->user()->id; + $mid = $request->input('mid'); + $ml = ModLog::whereUserId($uid)->findOrFail($mid)->delete(); + $msg = "Successfully deleted modlog comment!"; + $request->session()->flash('status', $msg); + return redirect('/i/admin/users/modlogs/' . $user->id); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 921312b3..f6b69343 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -21,7 +21,8 @@ use App\Http\Controllers\Admin\{ AdminReportController, AdminMediaController, AdminSettingsController, - AdminSupportController + AdminSupportController, + AdminUserController }; use Illuminate\Validation\Rule; use App\Services\AdminStatsService; @@ -32,11 +33,13 @@ class AdminController extends Controller AdminDiscoverController, AdminMediaController, AdminSettingsController, - AdminInstanceController; + AdminInstanceController, + AdminUserController; public function __construct() { $this->middleware('admin'); + $this->middleware('dangerzone'); $this->middleware('twofactor'); } @@ -46,25 +49,6 @@ class AdminController extends Controller return view('admin.home', compact('data')); } - public function users(Request $request) - { - $col = $request->query('col') ?? 'id'; - $dir = $request->query('dir') ?? 'desc'; - $users = User::select('id', 'username', 'status') - ->withCount('statuses') - ->orderBy($col, $dir) - ->simplePaginate(10); - - return view('admin.users.home', compact('users')); - } - - public function editUser(Request $request, $id) - { - $user = User::findOrFail($id); - $profile = $user->profile; - return view('admin.users.edit', compact('user', 'profile')); - } - public function statuses(Request $request) { $statuses = Status::orderBy('id', 'desc')->simplePaginate(10); @@ -109,22 +93,25 @@ class AdminController extends Controller 'nullable', 'string', Rule::in(['all', 'local', 'remote']) - ], - 'limit' => 'nullable|integer|min:1|max:50' + ] ]); $search = $request->input('search'); $filter = $request->input('filter'); $limit = 12; - if($search) { - $profiles = Profile::select('id','username') - ->where('username', 'like', "%$search%") - ->orderBy('id','desc') + $profiles = Profile::select('id','username') + ->whereNull('status') + ->when($search, function($q, $search) { + return $q->where('username', 'like', "%$search%"); + })->when($filter, function($q, $filter) { + if($filter == 'local') { + return $q->whereNull('domain'); + } + if($filter == 'remote') { + return $q->whereNotNull('domain'); + } + return $q; + })->orderByDesc('id') ->simplePaginate($limit); - } else if($filter) { - $profiles = Profile::select('id','username')->withCount(['likes','statuses','followers'])->orderBy($filter, $order)->simplePaginate($limit); - } else { - $profiles = Profile::select('id','username')->orderBy('id','desc')->simplePaginate($limit); - } return view('admin.profiles.home', compact('profiles')); } diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index f414dcf9..8eb4163d 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -152,7 +152,7 @@ class ApiV1Controller extends Controller $this->validate($request, [ 'display_name' => 'nullable|string', 'note' => 'nullable|string', - 'locked' => 'nullable|boolean', + 'locked' => 'nullable', // 'source.privacy' => 'nullable|in:unlisted,public,private', // 'source.sensitive' => 'nullable|boolean' ]); diff --git a/app/Http/Controllers/Api/BaseApiController.php b/app/Http/Controllers/Api/BaseApiController.php index a3a450c6..6b18f835 100644 --- a/app/Http/Controllers/Api/BaseApiController.php +++ b/app/Http/Controllers/Api/BaseApiController.php @@ -314,6 +314,10 @@ class BaseApiController extends Controller { $user = $request->user(); abort_if(!$user, 403); + if($user->status != null) { + Auth::logout(); + return redirect('/login'); + } $resource = new Fractal\Resource\Item($user->profile, new AccountTransformer()); $res = $this->fractal->createData($resource)->toArray(); return response()->json($res); diff --git a/app/Http/Controllers/CollectionController.php b/app/Http/Controllers/CollectionController.php index 4fc7dfe6..e8354367 100644 --- a/app/Http/Controllers/CollectionController.php +++ b/app/Http/Controllers/CollectionController.php @@ -50,13 +50,13 @@ class CollectionController extends Controller return $request->all(); } - public function store(Request $request, int $id) + public function store(Request $request, $id) { abort_if(!Auth::check(), 403); $this->validate($request, [ 'title' => 'nullable', 'description' => 'nullable', - 'visibility' => 'required|alpha|in:public,private' + 'visibility' => 'nullable|string|in:public,private' ]); $profile = Auth::user()->profile; @@ -140,7 +140,7 @@ class CollectionController extends Controller return 200; } - public function get(Request $request, int $id) + public function get(Request $request, $id) { $profile = Auth::check() ? Auth::user()->profile : []; diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index ec8fb920..acf41df4 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -23,11 +23,7 @@ class CommentController extends Controller { public function showAll(Request $request, $username, int $id) { - $profile = Profile::whereNull(['status', 'domain'])->whereUsername($username)->firstOrFail(); - $status = Status::whereProfileId($profile->id)->findOrFail($id); - $replies = Status::whereInReplyToId($id)->simplePaginate(40); - - return view('status.comments', compact('profile', 'status', 'replies')); + abort(404); } public function store(Request $request) diff --git a/app/Http/Controllers/NewsroomController.php b/app/Http/Controllers/NewsroomController.php index 7c2f7adb..507ffeb2 100644 --- a/app/Http/Controllers/NewsroomController.php +++ b/app/Http/Controllers/NewsroomController.php @@ -65,7 +65,7 @@ class NewsroomController extends Controller ->map(function($post) { return [ 'id' => $post->id, - 'title' => Str::limit($post->title, 25), + 'title' => Str::limit($post->title, 40), 'summary' => $post->summary, 'url' => $post->show_link ? $post->permalink() : null, 'published_at' => $post->published_at->format('F m, Y') diff --git a/app/Http/Controllers/TimelineController.php b/app/Http/Controllers/TimelineController.php index df9fb5e5..52267b2d 100644 --- a/app/Http/Controllers/TimelineController.php +++ b/app/Http/Controllers/TimelineController.php @@ -20,11 +20,19 @@ class TimelineController extends Controller public function local(Request $request) { - return view('timeline.local'); + $this->validate($request, [ + 'layout' => 'nullable|string|in:grid,feed' + ]); + $layout = $request->input('layout', 'feed'); + return view('timeline.local', compact('layout')); } public function network(Request $request) { - return view('timeline.network'); + $this->validate($request, [ + 'layout' => 'nullable|string|in:grid,feed' + ]); + $layout = $request->input('layout', 'feed'); + return view('timeline.network', compact('layout')); } } diff --git a/app/Http/Middleware/DangerZone.php b/app/Http/Middleware/DangerZone.php index d1a1b4af..5a43d6e6 100644 --- a/app/Http/Middleware/DangerZone.php +++ b/app/Http/Middleware/DangerZone.php @@ -16,6 +16,12 @@ class DangerZone */ public function handle($request, Closure $next) { + if( $request->session()->get('sudoModeAttempts') > 3) { + $request->session()->pull('redirectNext'); + $request->session()->pull('sudoModeAttempts'); + Auth::logout(); + return redirect(route('login')); + } if(!Auth::check()) { return redirect(route('login')); } diff --git a/app/Mail/AdminMessage.php b/app/Mail/AdminMessage.php new file mode 100644 index 00000000..249f6694 --- /dev/null +++ b/app/Mail/AdminMessage.php @@ -0,0 +1,37 @@ +msg = $msg; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $admins = config('pixelfed.domain.app') . ' admins'; + return $this->markdown('emails.notification.admin_message') + ->with(['msg' => $this->msg]) + ->subject('Message from ' . $admins); + } +} diff --git a/app/ModLog.php b/app/ModLog.php new file mode 100644 index 00000000..0e0b2b5e --- /dev/null +++ b/app/ModLog.php @@ -0,0 +1,48 @@ +belongsTo(User::class, 'user_id'); + } + + public function actionToText() + { + $msg = 'Unknown action'; + + switch ($this->action) { + case 'admin.user.mail': + $msg = "Sent Message"; + break; + + case 'admin.user.action.cw.warn': + $msg = "Sent CW reminder"; + break; + + case 'admin.user.edit': + $msg = "Changed Profile"; + break; + + case 'admin.user.moderate': + $msg = "Moderation"; + break; + + case 'admin.user.delete': + $msg = "Deleted Account"; + break; + + default: + $msg = 'Unknown action'; + break; + } + + return $msg; + } +} diff --git a/app/Services/ModLogService.php b/app/Services/ModLogService.php new file mode 100644 index 00000000..cdbf7212 --- /dev/null +++ b/app/Services/ModLogService.php @@ -0,0 +1,98 @@ +log = new \StdClass; + } + + public static function boot() + { + return new self; + } + + public function user(User $user) + { + $this->log->user = $user; + return $this; + } + + public function objectUid($val = null) + { + $this->log->object_uid = $val; + return $this; + } + + public function objectId($val = null) + { + $this->log->object_id = $val; + return $this; + } + + public function objectType($val = null) + { + $this->log->object_type = $val; + return $this; + } + + public function action($val = null) + { + $this->log->action = $val; + return $this; + } + + public function message($val = null) + { + $this->log->message = $val; + return $this; + } + + public function metadata(array $val = null) + { + $this->log->metadata = json_encode($val); + return $this; + } + + public function accessLevel($val = null) + { + if(!in_array($val, ['admin', 'mod'])) { + return $this; + } + $this->log->access_level = $val; + return $this; + } + + public function save($res = false) + { + $log = $this->log; + if(!isset($log->user)) { + throw new \Exception('Invalid ModLog attribute.'); + } + + $ml = new ModLog(); + $ml->user_id = $log->user->id; + $ml->user_username = $log->user->username; + $ml->object_uid = $log->object_uid ?? null; + $ml->object_id = $log->object_id ?? null; + $ml->object_type = $log->object_type ?? null; + $ml->action = $log->action ?? null; + $ml->message = $log->message ?? null; + $ml->metadata = $log->metadata ?? null; + $ml->access_level = $log->access_level ?? 'admin'; + $ml->save(); + + if($res == true) { + return $ml; + } else { + return; + } + } +} \ No newline at end of file diff --git a/app/Transformer/Api/StoryItemTransformer.php b/app/Transformer/Api/StoryItemTransformer.php index 3d10cb97..1fbd9c37 100644 --- a/app/Transformer/Api/StoryItemTransformer.php +++ b/app/Transformer/Api/StoryItemTransformer.php @@ -12,14 +12,15 @@ class StoryItemTransformer extends Fractal\TransformerAbstract public function transform(StoryItem $item) { return [ - 'id' => (string) Str::uuid(), + 'id' => (string) $item->id, 'type' => $item->type, - 'length' => $item->duration, + 'length' => $item->duration != 0 ? $item->duration : 3, 'src' => $item->url(), 'preview' => null, 'link' => null, 'linkText' => null, - 'time' => $item->updated_at->format('U'), + 'time' => $item->created_at->format('U'), + 'expires_at' => $item->created_at->addHours(24)->format('U'), 'seen' => $item->story->seen(), ]; } diff --git a/app/Transformer/Api/StoryTransformer.php b/app/Transformer/Api/StoryTransformer.php index e362470c..cf19ed80 100644 --- a/app/Transformer/Api/StoryTransformer.php +++ b/app/Transformer/Api/StoryTransformer.php @@ -16,19 +16,16 @@ class StoryTransformer extends Fractal\TransformerAbstract return [ 'id' => (string) $story->id, 'photo' => $story->profile->avatarUrl(), - 'name' => '', - 'link' => '', + 'name' => $story->profile->username, + 'link' => $story->profile->url(), 'lastUpdated' => $story->updated_at->format('U'), 'seen' => $story->seen(), - 'items' => [], ]; } public function includeItems(Story $story) { - $items = $story->items; - - return $this->collection($items, new StoryItemTransformer()); + return $this->item($story, new StoryItemTransformer()); } } diff --git a/app/User.php b/app/User.php index 72963400..717c4f31 100644 --- a/app/User.php +++ b/app/User.php @@ -83,4 +83,9 @@ class User extends Authenticatable return 'profile:storage:used:' . $this->id; } + public function accountLog() + { + return $this->hasMany(AccountLog::class); + } + } diff --git a/app/Util/Site/Config.php b/app/Util/Site/Config.php index 09662508..8304b73e 100644 --- a/app/Util/Site/Config.php +++ b/app/Util/Site/Config.php @@ -10,6 +10,7 @@ class Config { public static function get() { return Cache::remember('api:site:configuration', now()->addMinutes(30), function() { return [ + 'open_registration' => config('pixelfed.open_registration'), 'uploader' => [ 'max_photo_size' => config('pixelfed.max_photo_size'), 'max_caption_length' => config('pixelfed.max_caption_length'), @@ -35,6 +36,7 @@ class Config { ], 'site' => [ + 'name' => config('app.name', 'pixelfed'), 'domain' => config('pixelfed.domain.app'), 'url' => config('app.url'), 'description' => config('instance.description') diff --git a/database/migrations/2020_02_14_063209_create_mod_logs_table.php b/database/migrations/2020_02_14_063209_create_mod_logs_table.php new file mode 100644 index 00000000..9443452f --- /dev/null +++ b/database/migrations/2020_02_14_063209_create_mod_logs_table.php @@ -0,0 +1,40 @@ +bigIncrements('id'); + $table->bigInteger('user_id')->unsigned()->index(); + $table->string('user_username')->nullable(); + $table->bigInteger('object_uid')->nullable()->unsigned()->index(); + $table->bigInteger('object_id')->nullable()->unsigned()->index(); + $table->string('object_type')->nullable()->index(); + $table->string('action')->nullable(); + $table->text('message')->nullable(); + $table->json('metadata')->nullable(); + $table->string('access_level')->default('admin')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('mod_logs'); + } +} diff --git a/resources/views/admin/users/activity.blade.php b/resources/views/admin/users/activity.blade.php new file mode 100644 index 00000000..7634188e --- /dev/null +++ b/resources/views/admin/users/activity.blade.php @@ -0,0 +1,84 @@ +@extends('admin.partial.template-full') + +@section('section') +
+ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + +Recent Activity
+{{$log->created_at->diffForHumans()}}
+{{$log->message}}
++ IP: {{$log->ip_address}} +
++ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + +Are you sure you want to delete this account?
++
+ ++ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + +{{$profile->statusCount()}}
-Posts
-{{$profile->likes()->count()}}
-Likes
-{{$profile->reports()->count()}}
-Reports
-{{PrettyNumber::size($profile->media()->sum('size'))}}
-Storage Used
-Edit
+- {{$profile->username}} -
-- {{$profile->emailUrl()}} -
-- Member Since: {{$profile->created_at->format('M Y')}} -
-- ID - | -- Username - | -- Statuses - | -- Storage - | -- Actions - | -|||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- {{$user->id}} - | -
- ![]() |
- - {{$user->profile ? $user->profile->statusCount() : 0}} - | -- - | -
-
-
- View
-
+
+
+Users++
+
-
- {{$users->links()}}
-
+
+ Mod Logs
+
+
+ |
+
+ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + +Send Message
++ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + +Moderation Logs
+{{$log->message}}
+{{$log->message}}
+{{$log->created_at->diffForHumans()}}
+{{$log->actionToText()}}
++ by: {{$log->user_username}} +
++ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + +Mod Tools
++ {{$profile->statuses()->count()}} Posts + | + {{$profile->followers()->count()}} Followers + | + {{$profile->following()->count()}} Following +
+ + ++ {{$profile->name}} +
+ @if($user->is_admin == true) ++ ADMIN +
+ @endif ++ Joined {{$profile->created_at->diffForHumans()}} +
+bookmarks | +{{$profile->bookmarks()->count()}} | +
---|---|
collections | +{{$profile->collections()->count()}} | +
likes | +{{$profile->likes()->count()}} | +
reports | +{{$profile->reports()->count()}} | +
reported | +{{$profile->reported()->count()}} | +
Active stories | +{{$profile->stories()->count()}} | +
storage used | +{{PrettyNumber::size($profile->media()->sum('size'))}} / {{PrettyNumber::size(config('pixelfed.max_account_size') * 1000)}} | +
Recent Posts
+No statuses found
+
-
- {{ str_limit($status->profile->username, 15)}}
- {!! $status->rendered ?? e($status->caption) !!} {{$status->created_at->diffForHumans(null, true, true ,true)}}
-
All Comments
-
- -
- {{ str_limit($item->profile->username, 15)}}
-
-
- {!! $item->rendered ?? e($item->caption) !!}
-
- {{$item->created_at->diffForHumans(null, true, true ,true)}}
-
-
-
- @endforeach - -