Browse Source

Update AccountController

Daniel Supernault 6 years ago
parent
commit
213fba725e
2 changed files with 433 additions and 512 deletions
  1. 431 466
      app/Http/Controllers/AccountController.php
  2. 2 46
      app/Http/Controllers/InternalApiController.php

+ 431 - 466
app/Http/Controllers/AccountController.php

@@ -2,476 +2,441 @@
 
 namespace App\Http\Controllers;
 
-use App\EmailVerification;
-use App\Follower;
-use App\FollowRequest;
-use App\Jobs\FollowPipeline\FollowPipeline;
-use App\Mail\ConfirmEmail;
-use App\Notification;
-use App\Profile;
-use App\User;
-use App\UserFilter;
-use Auth;
-use Cache;
 use Carbon\Carbon;
+use App\Mail\ConfirmEmail;
 use Illuminate\Http\Request;
-use Mail;
-use Redis;
+use {Auth, Cache, Mail, Redis};
 use PragmaRX\Google2FA\Google2FA;
+use App\Jobs\FollowPipeline\FollowPipeline;
+use App\{
+	EmailVerification,
+	Follower,
+	FollowRequest,
+	Notification,
+	Profile,
+	User,
+	UserFilter
+};
 
 class AccountController extends Controller
 {
-    protected $filters = [
-      'user.mute',
-      'user.block',
-    ];
-
-    public function __construct()
-    {
-        $this->middleware('auth');
-    }
-
-    public function notifications(Request $request)
-    {
-        return view('account.activity');
-    }
-
-    public function followingActivity(Request $request)
-    {
-        $this->validate($request, [
-          'page' => 'nullable|min:1|max:3',
-          'a'    => 'nullable|alpha_dash',
-      ]);
-        $profile = Auth::user()->profile;
-        $action = $request->input('a');
-        $allowed = ['like', 'follow'];
-        $timeago = Carbon::now()->subMonths(3);
-        $following = $profile->following->pluck('id');
-        $notifications = Notification::whereIn('actor_id', $following)
-          ->whereIn('action', $allowed)
-          ->where('actor_id', '<>', $profile->id)
-          ->where('profile_id', '<>', $profile->id)
-          ->whereDate('created_at', '>', $timeago)
-          ->orderBy('notifications.created_at', 'desc')
-          ->simplePaginate(30);
-
-        return view('account.following', compact('profile', 'notifications'));
-    }
-
-    public function verifyEmail(Request $request)
-    {
-        return view('account.verify_email');
-    }
-
-    public function sendVerifyEmail(Request $request)
-    {
-        $recentAttempt = EmailVerification::whereUserId(Auth::id())
-          ->whereDate('created_at', '>', now()->subHours(12))->count();
-
-        if ($recentAttempt > 0) {
-            return redirect()->back()->with('error', 'A verification email has already been sent recently. Please check your email, or try again later.');
-        } 
-
-        EmailVerification::whereUserId(Auth::id())->delete();
-
-        $user = User::whereNull('email_verified_at')->find(Auth::id());
-        $utoken = str_random(40);
-        $rtoken = str_random(128);
-
-        $verify = new EmailVerification();
-        $verify->user_id = $user->id;
-        $verify->email = $user->email;
-        $verify->user_token = $utoken;
-        $verify->random_token = $rtoken;
-        $verify->save();
-
-        Mail::to($user->email)->send(new ConfirmEmail($verify));
-
-        return redirect()->back()->with('status', 'Verification email sent!');
-    }
-
-    public function confirmVerifyEmail(Request $request, $userToken, $randomToken)
-    {
-        $verify = EmailVerification::where('user_token', $userToken)
-          ->where('random_token', $randomToken)
-          ->firstOrFail();
-
-        if (Auth::id() === $verify->user_id &&
-          $verify->user_token === $userToken &&
-          $verify->random_token === $randomToken) {
-            $user = User::find(Auth::id());
-            $user->email_verified_at = Carbon::now();
-            $user->save();
-
-            return redirect('/');
-        } else {
-            abort(403);
-        }
-    }
-
-    public function fetchNotifications(int $id)
-    {
-        $key = config('cache.prefix').":user.{$id}.notifications";
-        $redis = Redis::connection();
-        $notifications = $redis->lrange($key, 0, 30);
-        if (empty($notifications)) {
-            $notifications = Notification::whereProfileId($id)
-          ->orderBy('id', 'desc')->take(30)->get();
-        } else {
-            $notifications = $this->hydrateNotifications($notifications);
-        }
-
-        return $notifications;
-    }
-
-    public function hydrateNotifications($keys)
-    {
-        $prefix = 'notification.';
-        $notifications = collect([]);
-        foreach ($keys as $key) {
-            $notifications->push(Cache::get("{$prefix}{$key}"));
-        }
-
-        return $notifications;
-    }
-
-    public function messages()
-    {
-        return view('account.messages');
-    }
-
-    public function direct()
-    {
-        return view('account.direct');
-    }
-
-    public function showMessage(Request $request, $id)
-    {
-        return view('account.message');
-    }
-
-    public function mute(Request $request)
-    {
-        $this->validate($request, [
-          'type' => 'required|alpha_dash',
-          'item' => 'required|integer|min:1',
-        ]);
-
-        $user = Auth::user()->profile;
-        $type = $request->input('type');
-        $item = $request->input('item');
-        $action = $type . '.mute';
-
-        if (!in_array($action, $this->filters)) {
-            return abort(406);
-        }
-        $filterable = [];
-        switch ($type) {
-          case 'user':
-            $profile = Profile::findOrFail($item);
-            if ($profile->id == $user->id) {
-                return abort(403);
-            }
-            $class = get_class($profile);
-            $filterable['id'] = $profile->id;
-            $filterable['type'] = $class;
-            break;
-
-          default:
-            // code...
-            break;
-        }
-
-        $filter = UserFilter::firstOrCreate([
-          'user_id'         => $user->id,
-          'filterable_id'   => $filterable['id'],
-          'filterable_type' => $filterable['type'],
-          'filter_type'     => 'mute',
-        ]);
-
-        $pid = $user->id;
-        Cache::forget("user:filter:list:$pid");
-        Cache::forget("feature:discover:posts:$pid");
-        Cache::forget("api:local:exp:rec:$pid");
-
-        return redirect()->back();
-    }
-
-    public function unmute(Request $request)
-    {
-        $this->validate($request, [
-          'type' => 'required|alpha_dash',
-          'item' => 'required|integer|min:1',
-        ]);
-
-        $user = Auth::user()->profile;
-        $type = $request->input('type');
-        $item = $request->input('item');
-        $action = $type . '.mute';
-
-        if (!in_array($action, $this->filters)) {
-            return abort(406);
-        }
-        $filterable = [];
-        switch ($type) {
-          case 'user':
-            $profile = Profile::findOrFail($item);
-            if ($profile->id == $user->id) {
-                return abort(403);
-            }
-            $class = get_class($profile);
-            $filterable['id'] = $profile->id;
-            $filterable['type'] = $class;
-            break;
-
-          default:
-            abort(400);
-            break;
-        }
-
-        $filter = UserFilter::whereUserId($user->id)
-            ->whereFilterableId($filterable['id'])
-            ->whereFilterableType($filterable['type'])
-            ->whereFilterType('mute')
-            ->first();
-
-        if($filter) {
-            $filter->delete();
-        }
-
-        $pid = $user->id;
-        Cache::forget("user:filter:list:$pid");
-        Cache::forget("feature:discover:posts:$pid");
-        Cache::forget("api:local:exp:rec:$pid");
-
-        if($request->wantsJson()) {
-            return response()->json([200]);
-        } else {
-            return redirect()->back();
-        }
-    }
-
-    public function block(Request $request)
-    {
-        $this->validate($request, [
-          'type' => 'required|alpha_dash',
-          'item' => 'required|integer|min:1',
-        ]);
-
-        $user = Auth::user()->profile;
-        $type = $request->input('type');
-        $item = $request->input('item');
-        $action = $type.'.block';
-        if (!in_array($action, $this->filters)) {
-            return abort(406);
-        }
-        $filterable = [];
-        switch ($type) {
-          case 'user':
-            $profile = Profile::findOrFail($item);
-            if ($profile->id == $user->id) {
-                return abort(403);
-            }
-            $class = get_class($profile);
-            $filterable['id'] = $profile->id;
-            $filterable['type'] = $class;
-
-            Follower::whereProfileId($profile->id)->whereFollowingId($user->id)->delete();
-            Notification::whereProfileId($user->id)->whereActorId($profile->id)->delete();
-            break;
-
-          default:
-            // code...
-            break;
-        }
-
-        $filter = UserFilter::firstOrCreate([
-          'user_id'         => $user->id,
-          'filterable_id'   => $filterable['id'],
-          'filterable_type' => $filterable['type'],
-          'filter_type'     => 'block',
-        ]);
-
-        $pid = $user->id;
-        Cache::forget("user:filter:list:$pid");
-        Cache::forget("feature:discover:posts:$pid");
-        Cache::forget("api:local:exp:rec:$pid");
-
-        return redirect()->back();
-    }
-
-
-    public function unblock(Request $request)
-    {
-        $this->validate($request, [
-          'type' => 'required|alpha_dash',
-          'item' => 'required|integer|min:1',
-        ]);
-
-        $user = Auth::user()->profile;
-        $type = $request->input('type');
-        $item = $request->input('item');
-        $action = $type . '.block';
-        if (!in_array($action, $this->filters)) {
-            return abort(406);
-        }
-        $filterable = [];
-        switch ($type) {
-          case 'user':
-            $profile = Profile::findOrFail($item);
-            if ($profile->id == $user->id) {
-                return abort(403);
-            }
-            $class = get_class($profile);
-            $filterable['id'] = $profile->id;
-            $filterable['type'] = $class;
-            break;
-
-          default:
-            abort(400);
-            break;
-        }
-
-
-        $filter = UserFilter::whereUserId($user->id)
-            ->whereFilterableId($filterable['id'])
-            ->whereFilterableType($filterable['type'])
-            ->whereFilterType('block')
-            ->first();
-
-        if($filter) {
-            $filter->delete();
-        }
-
-        $pid = $user->id;
-        Cache::forget("user:filter:list:$pid");
-        Cache::forget("feature:discover:posts:$pid");
-        Cache::forget("api:local:exp:rec:$pid");
-        
-        return redirect()->back();
-    }
-
-    public function followRequests(Request $request)
-    {
-        $pid = Auth::user()->profile->id;
-        $followers = FollowRequest::whereFollowingId($pid)->orderBy('id','desc')->whereIsRejected(0)->simplePaginate(10);
-        return view('account.follow-requests', compact('followers'));
-    }
-
-    public function followRequestHandle(Request $request)
-    {
-        $this->validate($request, [
-            'action' => 'required|string|max:10',
-            'id' => 'required|integer|min:1'
-        ]);
-
-        $pid = Auth::user()->profile->id;
-        $action = $request->input('action') === 'accept' ? 'accept' : 'reject';
-        $id = $request->input('id');
-        $followRequest = FollowRequest::whereFollowingId($pid)->findOrFail($id);
-        $follower = $followRequest->follower;
-
-        switch ($action) {
-            case 'accept':
-                $follow = new Follower();
-                $follow->profile_id = $follower->id;
-                $follow->following_id = $pid;
-                $follow->save();
-                FollowPipeline::dispatch($follow);
-                $followRequest->delete();
-                break;
-
-            case 'reject':
-                $followRequest->is_rejected = true;
-                $followRequest->save();
-                break;
-        }
-
-        return response()->json(['msg' => 'success'], 200);
-    }
-
-    public function sudoMode(Request $request)
-    {
-        return view('auth.sudo');
-    }
-
-    public function sudoModeVerify(Request $request)
-    {
-        $this->validate($request, [
-            'password' => 'required|string|max:500'
-        ]);
-        $user = Auth::user();
-        $password = $request->input('password');
-        $next = $request->session()->get('redirectNext', '/');
-        if(password_verify($password, $user->password) === true) {
-            $request->session()->put('sudoMode', time());
-            return redirect($next);
-        } else {
-            return redirect()
-                ->back()
-                ->withErrors(['password' => __('auth.failed')]);
-        }
-    }
-
-    public function twoFactorCheckpoint(Request $request)
-    {
-        return view('auth.checkpoint');
-    }
-
-    public function twoFactorVerify(Request $request)
-    {
-        $this->validate($request, [
-            'code'  => 'required|string|max:32'
-        ]);
-        $user = Auth::user();
-        $code = $request->input('code');
-        $google2fa = new Google2FA();
-        $verify = $google2fa->verifyKey($user->{'2fa_secret'}, $code);
-        if($verify) {
-            $request->session()->push('2fa.session.active', true);
-            return redirect('/');
-        } else {
-
-            if($this->twoFactorBackupCheck($request, $code, $user)) {
-                return redirect('/');
-            }
-
-            if($request->session()->has('2fa.attempts')) {
-                $count = (int) $request->session()->has('2fa.attempts');
-                $request->session()->push('2fa.attempts', $count + 1);
-            } else {
-                $request->session()->push('2fa.attempts', 1);
-            }
-            return redirect()->back()->withErrors([
-                'code' => 'Invalid code'
-            ]);
-        }
-    }
-
-    protected function twoFactorBackupCheck($request, $code, User $user)
-    {
-            $backupCodes = $user->{'2fa_backup_codes'};
-            if($backupCodes) {
-                $codes = json_decode($backupCodes, true);
-                foreach ($codes as $c) {
-                    if(hash_equals($c, $code)) {
-                        // remove code
-                        $codes = array_flatten(array_diff($codes, [$code]));
-                        $user->{'2fa_backup_codes'} = json_encode($codes);
-                        $user->save();
-                        $request->session()->push('2fa.session.active', true);
-                        return true;
-                    } else {
-                        return false;
-                    }
-                }
-            } else {
-                return false;
-            }  
-    }
-
-    public function accountRestored(Request $request)
-    {
-        //
-    }
+	protected $filters = [
+		'user.mute',
+		'user.block',
+	];
+
+	public function __construct()
+	{
+		$this->middleware('auth');
+	}
+
+	public function notifications(Request $request)
+	{
+		return view('account.activity');
+	}
+
+	public function followingActivity(Request $request)
+	{
+		$this->validate($request, [
+			'page' => 'nullable|min:1|max:3',
+			'a'    => 'nullable|alpha_dash',
+		]);
+
+		$action = $request->input('a');
+		$allowed = ['like', 'follow'];
+		$timeago = Carbon::now()->subMonths(3);
+
+		$profile = Auth::user()->profile;
+		$following = $profile->following->pluck('id');
+
+		$notifications = Notification::whereIn('actor_id', $following)
+		->whereIn('action', $allowed)
+		->where('actor_id', '<>', $profile->id)
+		->where('profile_id', '<>', $profile->id)
+		->whereDate('created_at', '>', $timeago)
+		->orderBy('notifications.created_at', 'desc')
+		->simplePaginate(30);
+
+		return view('account.following', compact('profile', 'notifications'));
+	}
+
+	public function verifyEmail(Request $request)
+	{
+		return view('account.verify_email');
+	}
+
+	public function sendVerifyEmail(Request $request)
+	{
+		$recentAttempt = EmailVerification::whereUserId(Auth::id())
+		->whereDate('created_at', '>', now()->subHours(12))->count();
+
+		if ($recentAttempt > 0) {
+			return redirect()->back()->with('error', 'A verification email has already been sent recently. Please check your email, or try again later.');
+		} 
+
+		EmailVerification::whereUserId(Auth::id())->delete();
+
+		$user = User::whereNull('email_verified_at')->find(Auth::id());
+		$utoken = str_random(64);
+		$rtoken = str_random(128);
+
+		$verify = new EmailVerification();
+		$verify->user_id = $user->id;
+		$verify->email = $user->email;
+		$verify->user_token = $utoken;
+		$verify->random_token = $rtoken;
+		$verify->save();
+
+		Mail::to($user->email)->send(new ConfirmEmail($verify));
+
+		return redirect()->back()->with('status', 'Verification email sent!');
+	}
+
+	public function confirmVerifyEmail(Request $request, $userToken, $randomToken)
+	{
+		$verify = EmailVerification::where('user_token', $userToken)
+		->where('created_at', '>', now()->subWeeks(2))
+		->where('random_token', $randomToken)
+		->firstOrFail();
+
+		if (Auth::id() === $verify->user_id && $verify->user_token === $userToken && $verify->random_token === $randomToken) {
+			$user = User::find(Auth::id());
+			$user->email_verified_at = Carbon::now();
+			$user->save();
+
+			return redirect('/');
+		} else {
+			abort(403);
+		}
+	}
+
+	public function messages()
+	{
+		return view('account.messages');
+	}
+
+	public function direct()
+	{
+		return view('account.direct');
+	}
+
+	public function showMessage(Request $request, $id)
+	{
+		return view('account.message');
+	}
+
+	public function mute(Request $request)
+	{
+		$this->validate($request, [
+			'type' => 'required|alpha_dash',
+			'item' => 'required|integer|min:1',
+		]);
+
+		$user = Auth::user()->profile;
+		$type = $request->input('type');
+		$item = $request->input('item');
+		$action = $type . '.mute';
+
+		if (!in_array($action, $this->filters)) {
+			return abort(406);
+		}
+		$filterable = [];
+		switch ($type) {
+			case 'user':
+			$profile = Profile::findOrFail($item);
+			if ($profile->id == $user->id) {
+				return abort(403);
+			}
+			$class = get_class($profile);
+			$filterable['id'] = $profile->id;
+			$filterable['type'] = $class;
+			break;
+		}
+
+		$filter = UserFilter::firstOrCreate([
+			'user_id'         => $user->id,
+			'filterable_id'   => $filterable['id'],
+			'filterable_type' => $filterable['type'],
+			'filter_type'     => 'mute',
+		]);
+
+		$pid = $user->id;
+		Cache::forget("user:filter:list:$pid");
+		Cache::forget("feature:discover:posts:$pid");
+		Cache::forget("api:local:exp:rec:$pid");
+
+		return redirect()->back();
+	}
+
+	public function unmute(Request $request)
+	{
+		$this->validate($request, [
+			'type' => 'required|alpha_dash',
+			'item' => 'required|integer|min:1',
+		]);
+
+		$user = Auth::user()->profile;
+		$type = $request->input('type');
+		$item = $request->input('item');
+		$action = $type . '.mute';
+
+		if (!in_array($action, $this->filters)) {
+			return abort(406);
+		}
+		$filterable = [];
+		switch ($type) {
+			case 'user':
+			$profile = Profile::findOrFail($item);
+			if ($profile->id == $user->id) {
+				return abort(403);
+			}
+			$class = get_class($profile);
+			$filterable['id'] = $profile->id;
+			$filterable['type'] = $class;
+			break;
+
+			default:
+			abort(400);
+			break;
+		}
+
+		$filter = UserFilter::whereUserId($user->id)
+		->whereFilterableId($filterable['id'])
+		->whereFilterableType($filterable['type'])
+		->whereFilterType('mute')
+		->first();
+
+		if($filter) {
+			$filter->delete();
+		}
+
+		$pid = $user->id;
+		Cache::forget("user:filter:list:$pid");
+		Cache::forget("feature:discover:posts:$pid");
+		Cache::forget("api:local:exp:rec:$pid");
+
+		if($request->wantsJson()) {
+			return response()->json([200]);
+		} else {
+			return redirect()->back();
+		}
+	}
+
+	public function block(Request $request)
+	{
+		$this->validate($request, [
+			'type' => 'required|alpha_dash',
+			'item' => 'required|integer|min:1',
+		]);
+
+		$user = Auth::user()->profile;
+		$type = $request->input('type');
+		$item = $request->input('item');
+		$action = $type.'.block';
+		if (!in_array($action, $this->filters)) {
+			return abort(406);
+		}
+		$filterable = [];
+		switch ($type) {
+			case 'user':
+			$profile = Profile::findOrFail($item);
+			if ($profile->id == $user->id) {
+				return abort(403);
+			}
+			$class = get_class($profile);
+			$filterable['id'] = $profile->id;
+			$filterable['type'] = $class;
+
+			Follower::whereProfileId($profile->id)->whereFollowingId($user->id)->delete();
+			Notification::whereProfileId($user->id)->whereActorId($profile->id)->delete();
+			break;
+		}
+
+		$filter = UserFilter::firstOrCreate([
+			'user_id'         => $user->id,
+			'filterable_id'   => $filterable['id'],
+			'filterable_type' => $filterable['type'],
+			'filter_type'     => 'block',
+		]);
+
+		$pid = $user->id;
+		Cache::forget("user:filter:list:$pid");
+		Cache::forget("feature:discover:posts:$pid");
+		Cache::forget("api:local:exp:rec:$pid");
+
+		return redirect()->back();
+	}
+
+
+	public function unblock(Request $request)
+	{
+		$this->validate($request, [
+			'type' => 'required|alpha_dash',
+			'item' => 'required|integer|min:1',
+		]);
+
+		$user = Auth::user()->profile;
+		$type = $request->input('type');
+		$item = $request->input('item');
+		$action = $type . '.block';
+		if (!in_array($action, $this->filters)) {
+			return abort(406);
+		}
+		$filterable = [];
+		switch ($type) {
+			case 'user':
+			$profile = Profile::findOrFail($item);
+			if ($profile->id == $user->id) {
+				return abort(403);
+			}
+			$class = get_class($profile);
+			$filterable['id'] = $profile->id;
+			$filterable['type'] = $class;
+			break;
+
+			default:
+			abort(400);
+			break;
+		}
+
+
+		$filter = UserFilter::whereUserId($user->id)
+		->whereFilterableId($filterable['id'])
+		->whereFilterableType($filterable['type'])
+		->whereFilterType('block')
+		->first();
+
+		if($filter) {
+			$filter->delete();
+		}
+
+		$pid = $user->id;
+		Cache::forget("user:filter:list:$pid");
+		Cache::forget("feature:discover:posts:$pid");
+		Cache::forget("api:local:exp:rec:$pid");
+
+		return redirect()->back();
+	}
+
+	public function followRequests(Request $request)
+	{
+		$pid = Auth::user()->profile->id;
+		$followers = FollowRequest::whereFollowingId($pid)->orderBy('id','desc')->whereIsRejected(0)->simplePaginate(10);
+		return view('account.follow-requests', compact('followers'));
+	}
+
+	public function followRequestHandle(Request $request)
+	{
+		$this->validate($request, [
+			'action' => 'required|string|max:10',
+			'id' => 'required|integer|min:1'
+		]);
+
+		$pid = Auth::user()->profile->id;
+		$action = $request->input('action') === 'accept' ? 'accept' : 'reject';
+		$id = $request->input('id');
+		$followRequest = FollowRequest::whereFollowingId($pid)->findOrFail($id);
+		$follower = $followRequest->follower;
+
+		switch ($action) {
+			case 'accept':
+			$follow = new Follower();
+			$follow->profile_id = $follower->id;
+			$follow->following_id = $pid;
+			$follow->save();
+			FollowPipeline::dispatch($follow);
+			$followRequest->delete();
+			break;
+
+			case 'reject':
+			$followRequest->is_rejected = true;
+			$followRequest->save();
+			break;
+		}
+
+		return response()->json(['msg' => 'success'], 200);
+	}
+
+	public function sudoMode(Request $request)
+	{
+		return view('auth.sudo');
+	}
+
+	public function sudoModeVerify(Request $request)
+	{
+		$this->validate($request, [
+			'password' => 'required|string|max:500'
+		]);
+		$user = Auth::user();
+		$password = $request->input('password');
+		$next = $request->session()->get('redirectNext', '/');
+		if(password_verify($password, $user->password) === true) {
+			$request->session()->put('sudoMode', time());
+			return redirect($next);
+		} else {
+			return redirect()
+			->back()
+			->withErrors(['password' => __('auth.failed')]);
+		}
+	}
+
+	public function twoFactorCheckpoint(Request $request)
+	{
+		return view('auth.checkpoint');
+	}
+
+	public function twoFactorVerify(Request $request)
+	{
+		$this->validate($request, [
+			'code'  => 'required|string|max:32'
+		]);
+		$user = Auth::user();
+		$code = $request->input('code');
+		$google2fa = new Google2FA();
+		$verify = $google2fa->verifyKey($user->{'2fa_secret'}, $code);
+		if($verify) {
+			$request->session()->push('2fa.session.active', true);
+			return redirect('/');
+		} else {
+
+			if($this->twoFactorBackupCheck($request, $code, $user)) {
+				return redirect('/');
+			}
+
+			if($request->session()->has('2fa.attempts')) {
+				$count = (int) $request->session()->has('2fa.attempts');
+				$request->session()->push('2fa.attempts', $count + 1);
+			} else {
+				$request->session()->push('2fa.attempts', 1);
+			}
+			return redirect()->back()->withErrors([
+				'code' => 'Invalid code'
+			]);
+		}
+	}
+
+	protected function twoFactorBackupCheck($request, $code, User $user)
+	{
+		$backupCodes = $user->{'2fa_backup_codes'};
+		if($backupCodes) {
+			$codes = json_decode($backupCodes, true);
+			foreach ($codes as $c) {
+				if(hash_equals($c, $code)) {
+					$codes = array_flatten(array_diff($codes, [$code]));
+					$user->{'2fa_backup_codes'} = json_encode($codes);
+					$user->save();
+					$request->session()->push('2fa.session.active', true);
+					return true;
+				} else {
+					return false;
+				}
+			}
+		} else {
+			return false;
+		}  
+	}
+
+	public function accountRestored(Request $request)
+	{
+	}
 }

+ 2 - 46
app/Http/Controllers/InternalApiController.php

@@ -50,38 +50,7 @@ class InternalApiController extends Controller
     // deprecated
     public function discover(Request $request)
     {
-        $profile = Auth::user()->profile;
-        $pid = $profile->id;
-        $following = Cache::remember('feature:discover:following:'.$pid, now()->addMinutes(60), function() use ($pid) {
-            return Follower::whereProfileId($pid)->pluck('following_id')->toArray();
-        });
-        $filters = Cache::remember("user:filter:list:$pid", now()->addMinutes(60), function() use($pid) {
-            return UserFilter::whereUserId($pid)
-            ->whereFilterableType('App\Profile')
-            ->whereIn('filter_type', ['mute', 'block'])
-            ->pluck('filterable_id')->toArray();
-        });
-        $following = array_merge($following, $filters);
-
-        $posts = Status::select('id', 'caption', 'profile_id')
-              ->whereHas('media')
-              ->whereIsNsfw(false)
-              ->whereVisibility('public')
-              ->whereNotIn('profile_id', $following)
-              ->with('media')
-              ->orderBy('created_at', 'desc')
-              ->take(21)
-              ->get();
-
-        $res = [
-            'posts' => $posts->map(function($post) {
-                return [
-                    'url' => $post->url(),
-                    'thumb' => $post->thumb(),
-                ];
-            })
-        ];
-        return response()->json($res, 200, [], JSON_PRETTY_PRINT);
+        return;
     }
 
     public function discoverPosts(Request $request)
@@ -155,22 +124,9 @@ class InternalApiController extends Controller
         return response()->json(compact('msg', 'profile', 'thread'), 200, [], JSON_PRETTY_PRINT);
     }
 
-    public function notificationMarkAllRead(Request $request)
-    {
-        $profile = Auth::user()->profile;
-
-        $notifications = Notification::whereProfileId($profile->id)->get();
-        foreach($notifications as $n) {
-            $n->read_at = Carbon::now();
-            $n->save();
-        }
-
-        return;
-    }
-
     public function statusReplies(Request $request, int $id)
     {
-        $parent = Status::findOrFail($id);
+        $parent = Status::whereScope('public')->findOrFail($id);
 
         $children = Status::whereInReplyToId($parent->id)
             ->orderBy('created_at', 'desc')