ProfileController.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Auth;
  5. use Cache;
  6. use View;
  7. use App\Follower;
  8. use App\FollowRequest;
  9. use App\Profile;
  10. use App\Story;
  11. use App\User;
  12. use App\UserFilter;
  13. use League\Fractal;
  14. use App\Services\AccountService;
  15. use App\Services\FollowerService;
  16. use App\Util\Lexer\Nickname;
  17. use App\Util\Webfinger\Webfinger;
  18. use App\Transformer\ActivityPub\ProfileOutbox;
  19. use App\Transformer\ActivityPub\ProfileTransformer;
  20. class ProfileController extends Controller
  21. {
  22. public function show(Request $request, $username)
  23. {
  24. $user = Profile::whereNull('domain')
  25. ->whereNull('status')
  26. ->whereUsername($username)
  27. ->firstOrFail();
  28. if($request->wantsJson() && config_cache('federation.activitypub.enabled')) {
  29. return $this->showActivityPub($request, $user);
  30. }
  31. return $this->buildProfile($request, $user);
  32. }
  33. protected function buildProfile(Request $request, $user)
  34. {
  35. $username = $user->username;
  36. $loggedIn = Auth::check();
  37. $isPrivate = false;
  38. $isBlocked = false;
  39. if(!$loggedIn) {
  40. $key = 'profile:settings:' . $user->id;
  41. $ttl = now()->addHours(6);
  42. $settings = Cache::remember($key, $ttl, function() use($user) {
  43. return $user->user->settings;
  44. });
  45. if ($user->is_private == true) {
  46. $profile = null;
  47. return view('profile.private', compact('user'));
  48. }
  49. $owner = false;
  50. $is_following = false;
  51. $profile = $user;
  52. $settings = [
  53. 'crawlable' => $settings->crawlable,
  54. 'following' => [
  55. 'count' => $settings->show_profile_following_count,
  56. 'list' => $settings->show_profile_following
  57. ],
  58. 'followers' => [
  59. 'count' => $settings->show_profile_follower_count,
  60. 'list' => $settings->show_profile_followers
  61. ]
  62. ];
  63. $ui = $request->has('ui') && $request->input('ui') == 'memory' ? 'profile.memory' : 'profile.show';
  64. return view($ui, compact('profile', 'settings'));
  65. } else {
  66. $key = 'profile:settings:' . $user->id;
  67. $ttl = now()->addHours(6);
  68. $settings = Cache::remember($key, $ttl, function() use($user) {
  69. return $user->user->settings;
  70. });
  71. if ($user->is_private == true) {
  72. $isPrivate = $this->privateProfileCheck($user, $loggedIn);
  73. }
  74. $isBlocked = $this->blockedProfileCheck($user);
  75. $owner = $loggedIn && Auth::id() === $user->user_id;
  76. $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
  77. if ($isPrivate == true || $isBlocked == true) {
  78. $requested = Auth::check() ? FollowRequest::whereFollowerId(Auth::user()->profile_id)
  79. ->whereFollowingId($user->id)
  80. ->exists() : false;
  81. return view('profile.private', compact('user', 'is_following', 'requested'));
  82. }
  83. $is_admin = is_null($user->domain) ? $user->user->is_admin : false;
  84. $profile = $user;
  85. $settings = [
  86. 'crawlable' => $settings->crawlable,
  87. 'following' => [
  88. 'count' => $settings->show_profile_following_count,
  89. 'list' => $settings->show_profile_following
  90. ],
  91. 'followers' => [
  92. 'count' => $settings->show_profile_follower_count,
  93. 'list' => $settings->show_profile_followers
  94. ]
  95. ];
  96. $ui = $request->has('ui') && $request->input('ui') == 'memory' ? 'profile.memory' : 'profile.show';
  97. return view($ui, compact('profile', 'settings'));
  98. }
  99. }
  100. public function permalinkRedirect(Request $request, $username)
  101. {
  102. $user = Profile::whereNull('domain')->whereUsername($username)->firstOrFail();
  103. if ($request->wantsJson() && config_cache('federation.activitypub.enabled')) {
  104. return $this->showActivityPub($request, $user);
  105. }
  106. return redirect($user->url());
  107. }
  108. protected function privateProfileCheck(Profile $profile, $loggedIn)
  109. {
  110. if (!Auth::check()) {
  111. return true;
  112. }
  113. $user = Auth::user()->profile;
  114. if($user->id == $profile->id || !$profile->is_private) {
  115. return false;
  116. }
  117. $follows = Follower::whereProfileId($user->id)->whereFollowingId($profile->id)->exists();
  118. if ($follows == false) {
  119. return true;
  120. }
  121. return false;
  122. }
  123. public static function accountCheck(Profile $profile)
  124. {
  125. switch ($profile->status) {
  126. case 'disabled':
  127. case 'suspended':
  128. case 'delete':
  129. return view('profile.disabled');
  130. break;
  131. default:
  132. break;
  133. }
  134. return abort(404);
  135. }
  136. protected function blockedProfileCheck(Profile $profile)
  137. {
  138. $pid = Auth::user()->profile->id;
  139. $blocks = UserFilter::whereUserId($profile->id)
  140. ->whereFilterType('block')
  141. ->whereFilterableType('App\Profile')
  142. ->pluck('filterable_id')
  143. ->toArray();
  144. if (in_array($pid, $blocks)) {
  145. return true;
  146. }
  147. return false;
  148. }
  149. public function showActivityPub(Request $request, $user)
  150. {
  151. abort_if(!config_cache('federation.activitypub.enabled'), 404);
  152. abort_if($user->domain, 404);
  153. $fractal = new Fractal\Manager();
  154. $resource = new Fractal\Resource\Item($user, new ProfileTransformer);
  155. $res = $fractal->createData($resource)->toArray();
  156. return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json');
  157. }
  158. public function showAtomFeed(Request $request, $user)
  159. {
  160. abort_if(!config('federation.atom.enabled'), 404);
  161. $profile = $user = Profile::whereNull('status')->whereNull('domain')->whereUsername($user)->whereIsPrivate(false)->firstOrFail();
  162. if($profile->status != null) {
  163. return $this->accountCheck($profile);
  164. }
  165. if($profile->is_private || Auth::check()) {
  166. $blocked = $this->blockedProfileCheck($profile);
  167. $check = $this->privateProfileCheck($profile, null);
  168. if($check || $blocked) {
  169. return redirect($profile->url());
  170. }
  171. }
  172. $items = $profile->statuses()->whereHas('media')->whereIn('visibility',['public', 'unlisted'])->orderBy('created_at', 'desc')->take(10)->get();
  173. return response()->view('atom.user', compact('profile', 'items'))
  174. ->header('Content-Type', 'application/atom+xml');
  175. }
  176. public function meRedirect()
  177. {
  178. abort_if(!Auth::check(), 404);
  179. return redirect(Auth::user()->url());
  180. }
  181. public function embed(Request $request, $username)
  182. {
  183. $res = view('profile.embed-removed');
  184. if(strlen($username) > 15 || strlen($username) < 2) {
  185. return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
  186. }
  187. $profile = Profile::whereUsername($username)
  188. ->whereIsPrivate(false)
  189. ->whereNull('status')
  190. ->whereNull('domain')
  191. ->first();
  192. if(!$profile) {
  193. return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
  194. }
  195. if(AccountService::canEmbed($profile->user_id) == false) {
  196. return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
  197. }
  198. $profile = AccountService::get($profile->id);
  199. return view('profile.embed', compact('profile'))->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
  200. }
  201. public function stories(Request $request, $username)
  202. {
  203. abort_if(!config_cache('instance.stories.enabled') || !$request->user(), 404);
  204. $profile = Profile::whereNull('domain')->whereUsername($username)->firstOrFail();
  205. $pid = $profile->id;
  206. $authed = Auth::user()->profile_id;
  207. abort_if($pid != $authed && !FollowerService::follows($authed, $pid), 404);
  208. $exists = Story::whereProfileId($pid)
  209. ->whereActive(true)
  210. ->exists();
  211. abort_unless($exists, 404);
  212. return view('profile.story', compact('pid', 'profile'));
  213. }
  214. }