Implement proper OAuth authorization on API endpoints

This commit is contained in:
Emelia Smith 2024-02-08 02:48:17 +01:00
parent 9330cd02f7
commit 0f8e45fe75
No known key found for this signature in database
6 changed files with 269 additions and 143 deletions

View file

@ -125,11 +125,15 @@ class ApiV1Controller extends Controller
return response()->json($res, $code, $headers, JSON_UNESCAPED_SLASHES); return response()->json($res, $code, $headers, JSON_UNESCAPED_SLASHES);
} }
/**
* GET /api/v1/apps/verify_credentials
*/
public function getApp(Request $request) public function getApp(Request $request)
{ {
if(!$request->user()) { # FIXME: /api/v1/apps/verify_credentials should be accessible with any
return response('', 403); # valid Access Token, not just a user's access token (i.e., client
} # credentails grant flow access tokens)
abort_if(!$request->user() || !$request->user()->token(), 403);
$client = $request->user()->token()->client; $client = $request->user()->token()->client;
$res = [ $res = [
@ -141,6 +145,9 @@ class ApiV1Controller extends Controller
return $this->json($res); return $this->json($res);
} }
/**
* POST /api/v1/apps
*/
public function apps(Request $request) public function apps(Request $request)
{ {
abort_if(!config_cache('pixelfed.oauth_enabled'), 404); abort_if(!config_cache('pixelfed.oauth_enabled'), 404);
@ -187,9 +194,11 @@ class ApiV1Controller extends Controller
*/ */
public function verifyCredentials(Request $request) public function verifyCredentials(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
AccountService::setLastActive($user->id); AccountService::setLastActive($user->id);
@ -215,6 +224,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountById(Request $request, $id) public function accountById(Request $request, $id)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$res = $request->has(self::PF_API_ENTITY_KEY) ? AccountService::get($id, true) : AccountService::getMastodon($id, true); $res = $request->has(self::PF_API_ENTITY_KEY) ? AccountService::get($id, true) : AccountService::getMastodon($id, true);
if(!$res) { if(!$res) {
return response()->json(['error' => 'Record not found'], 404); return response()->json(['error' => 'Record not found'], 404);
@ -233,7 +245,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountUpdateCredentials(Request $request) public function accountUpdateCredentials(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_api')) { if(config('pixelfed.bouncer.cloud_ips.ban_api')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -476,7 +489,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountFollowersById(Request $request, $id) public function accountFollowersById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$account = AccountService::get($id); $account = AccountService::get($id);
abort_if(!$account, 404); abort_if(!$account, 404);
@ -573,7 +587,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountFollowingById(Request $request, $id) public function accountFollowingById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$account = AccountService::get($id); $account = AccountService::get($id);
abort_if(!$account, 404); abort_if(!$account, 404);
@ -670,6 +685,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountStatusesById(Request $request, $id) public function accountStatusesById(Request $request, $id)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
$this->validate($request, [ $this->validate($request, [
@ -774,7 +792,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountFollowById(Request $request, $id) public function accountFollowById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follow'), 403);
$user = $request->user(); $user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-follow', $user->id), 403, 'Invalid permissions for this action'); abort_if($user->has_roles && !UserRoleService::can('can-follow', $user->id), 403, 'Invalid permissions for this action');
@ -866,7 +885,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountUnfollowById(Request $request, $id) public function accountUnfollowById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follow'), 403);
$user = $request->user(); $user = $request->user();
@ -936,7 +956,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountRelationshipsById(Request $request) public function accountRelationshipsById(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'id' => 'required|array|min:1|max:20', 'id' => 'required|array|min:1|max:20',
@ -965,7 +986,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountSearch(Request $request) public function accountSearch(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'q' => 'required|string|min:1|max:255', 'q' => 'required|string|min:1|max:255',
@ -1008,7 +1030,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountBlocks(Request $request) public function accountBlocks(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'nullable|integer|min:1|max:40', 'limit' => 'nullable|integer|min:1|max:40',
@ -1045,7 +1068,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountBlockById(Request $request, $id) public function accountBlockById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
$pid = $user->profile_id ?? $user->profile->id; $pid = $user->profile_id ?? $user->profile->id;
@ -1138,7 +1162,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountUnblockById(Request $request, $id) public function accountUnblockById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
$pid = $user->profile_id ?? $user->profile->id; $pid = $user->profile_id ?? $user->profile->id;
@ -1189,7 +1214,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountDomainBlocks(Request $request) public function accountDomainBlocks(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return response()->json([]); return response()->json([]);
} }
@ -1202,7 +1229,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountEndorsements(Request $request) public function accountEndorsements(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return response()->json([]); return response()->json([]);
} }
@ -1215,7 +1244,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountFavourites(Request $request) public function accountFavourites(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'sometimes|integer|min:1|max:40' 'limit' => 'sometimes|integer|min:1|max:40'
]); ]);
@ -1271,7 +1302,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusFavouriteById(Request $request, $id) public function statusFavouriteById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-like', $user->id), 403, 'Invalid permissions for this action'); abort_if($user->has_roles && !UserRoleService::can('can-like', $user->id), 403, 'Invalid permissions for this action');
@ -1338,7 +1370,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusUnfavouriteById(Request $request, $id) public function statusUnfavouriteById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-like', $user->id), 403, 'Invalid permissions for this action'); abort_if($user->has_roles && !UserRoleService::can('can-like', $user->id), 403, 'Invalid permissions for this action');
@ -1381,7 +1414,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountFilters(Request $request) public function accountFilters(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return response()->json([]); return response()->json([]);
} }
@ -1395,7 +1429,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountFollowRequests(Request $request) public function accountFollowRequests(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'sometimes|integer|min:1|max:100' 'limit' => 'sometimes|integer|min:1|max:100'
]); ]);
@ -1425,7 +1461,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountFollowRequestAccept(Request $request, $id) public function accountFollowRequestAccept(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follow'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$target = AccountService::getMastodon($id); $target = AccountService::getMastodon($id);
@ -1482,7 +1520,9 @@ class ApiV1Controller extends Controller
*/ */
public function accountFollowRequestReject(Request $request, $id) public function accountFollowRequestReject(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follow'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$target = AccountService::getMastodon($id); $target = AccountService::getMastodon($id);
@ -1518,7 +1558,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountSuggestions(Request $request) public function accountSuggestions(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
// todo // todo
@ -1619,7 +1660,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountLists(Request $request) public function accountLists(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return response()->json([]); return response()->json([]);
} }
@ -1633,7 +1675,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountListsById(Request $request, $id) public function accountListsById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return response()->json([]); return response()->json([]);
} }
@ -1646,7 +1689,8 @@ class ApiV1Controller extends Controller
*/ */
public function mediaUpload(Request $request) public function mediaUpload(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'file.*' => [ 'file.*' => [
@ -1782,7 +1826,8 @@ class ApiV1Controller extends Controller
*/ */
public function mediaUpdate(Request $request, $id) public function mediaUpdate(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'description' => 'nullable|string|max:' . config_cache('pixelfed.max_altext_length') 'description' => 'nullable|string|max:' . config_cache('pixelfed.max_altext_length')
@ -1835,7 +1880,8 @@ class ApiV1Controller extends Controller
*/ */
public function mediaGet(Request $request, $id) public function mediaGet(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action');
@ -1858,7 +1904,8 @@ class ApiV1Controller extends Controller
*/ */
public function mediaUploadV2(Request $request) public function mediaUploadV2(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'file.*' => [ 'file.*' => [
@ -1999,7 +2046,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountMutes(Request $request) public function accountMutes(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'nullable|integer|min:1|max:40' 'limit' => 'nullable|integer|min:1|max:40'
@ -2034,7 +2082,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountMuteById(Request $request, $id) public function accountMuteById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
$pid = $user->profile_id; $pid = $user->profile_id;
@ -2092,7 +2141,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountUnmuteById(Request $request, $id) public function accountUnmuteById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
$pid = $user->profile_id; $pid = $user->profile_id;
@ -2128,7 +2178,8 @@ class ApiV1Controller extends Controller
*/ */
public function accountNotifications(Request $request) public function accountNotifications(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'nullable|integer|min:1|max:100', 'limit' => 'nullable|integer|min:1|max:100',
@ -2204,7 +2255,10 @@ class ApiV1Controller extends Controller
*/ */
public function timelineHome(Request $request) public function timelineHome(Request $request)
{ {
$this->validate($request,[ abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [
'page' => 'sometimes|integer|max:40', 'page' => 'sometimes|integer|max:40',
'min_id' => 'sometimes|integer|min:0|max:' . PHP_INT_MAX, 'min_id' => 'sometimes|integer|min:0|max:' . PHP_INT_MAX,
'max_id' => 'sometimes|integer|min:0|max:' . PHP_INT_MAX, 'max_id' => 'sometimes|integer|min:0|max:' . PHP_INT_MAX,
@ -2606,7 +2660,9 @@ class ApiV1Controller extends Controller
*/ */
public function conversations(Request $request) public function conversations(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'min:1|max:40', 'limit' => 'min:1|max:40',
'scope' => 'nullable|in:inbox,sent,requests' 'scope' => 'nullable|in:inbox,sent,requests'
@ -2683,7 +2739,9 @@ class ApiV1Controller extends Controller
*/ */
public function statusById(Request $request, $id) public function statusById(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
AccountService::setLastActive($request->user()->id); AccountService::setLastActive($request->user()->id);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
@ -2730,7 +2788,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusContext(Request $request, $id) public function statusContext(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
AccountService::setLastActive($user->id); AccountService::setLastActive($user->id);
@ -2803,7 +2862,9 @@ class ApiV1Controller extends Controller
*/ */
public function statusCard(Request $request, $id) public function statusCard(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$res = []; $res = [];
return response()->json($res); return response()->json($res);
} }
@ -2817,7 +2878,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusRebloggedBy(Request $request, $id) public function statusRebloggedBy(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'sometimes|integer|min:1|max:80' 'limit' => 'sometimes|integer|min:1|max:80'
@ -2913,7 +2975,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusFavouritedBy(Request $request, $id) public function statusFavouritedBy(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'nullable|integer|min:1|max:80' 'limit' => 'nullable|integer|min:1|max:80'
@ -3010,7 +3073,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusCreate(Request $request) public function statusCreate(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'status' => 'nullable|string', 'status' => 'nullable|string',
@ -3225,7 +3289,9 @@ class ApiV1Controller extends Controller
*/ */
public function statusDelete(Request $request, $id) public function statusDelete(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
AccountService::setLastActive($request->user()->id); AccountService::setLastActive($request->user()->id);
$status = Status::whereProfileId($request->user()->profile->id) $status = Status::whereProfileId($request->user()->profile->id)
->findOrFail($id); ->findOrFail($id);
@ -3251,7 +3317,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusShare(Request $request, $id) public function statusShare(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-share', $user->id), 403, 'Invalid permissions for this action'); abort_if($user->has_roles && !UserRoleService::can('can-share', $user->id), 403, 'Invalid permissions for this action');
@ -3303,7 +3370,8 @@ class ApiV1Controller extends Controller
*/ */
public function statusUnshare(Request $request, $id) public function statusUnshare(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-share', $user->id), 403, 'Invalid permissions for this action'); abort_if($user->has_roles && !UserRoleService::can('can-share', $user->id), 403, 'Invalid permissions for this action');
@ -3346,7 +3414,8 @@ class ApiV1Controller extends Controller
*/ */
public function timelineHashtag(Request $request, $hashtag) public function timelineHashtag(Request $request, $hashtag)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request,[ $this->validate($request,[
'page' => 'nullable|integer|max:40', 'page' => 'nullable|integer|max:40',
@ -3447,7 +3516,8 @@ class ApiV1Controller extends Controller
*/ */
public function bookmarks(Request $request) public function bookmarks(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'nullable|integer|min:1|max:40', 'limit' => 'nullable|integer|min:1|max:40',
@ -3514,7 +3584,8 @@ class ApiV1Controller extends Controller
*/ */
public function bookmarkStatus(Request $request, $id) public function bookmarkStatus(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
@ -3554,7 +3625,8 @@ class ApiV1Controller extends Controller
*/ */
public function unbookmarkStatus(Request $request, $id) public function unbookmarkStatus(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
@ -3586,7 +3658,8 @@ class ApiV1Controller extends Controller
*/ */
public function discoverPosts(Request $request) public function discoverPosts(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'integer|min:1|max:40' 'limit' => 'integer|min:1|max:40'
@ -3596,29 +3669,30 @@ class ApiV1Controller extends Controller
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$filters = UserFilterService::filters($pid); $filters = UserFilterService::filters($pid);
$forYou = DiscoverService::getForYou(); $forYou = DiscoverService::getForYou();
$posts = $forYou->take(50)->map(function($post) { $posts = $forYou->take(50)->map(function ($post) {
return StatusService::getMastodon($post); return StatusService::getMastodon($post);
}) })
->filter(function($post) use($filters) { ->filter(function ($post) use ($filters) {
return $post && return $post &&
isset($post['account']) && isset($post['account']) &&
isset($post['account']['id']) && isset($post['account']['id']) &&
!in_array($post['account']['id'], $filters); !in_array($post['account']['id'], $filters);
}) })
->take(12) ->take(12)
->values(); ->values();
return $this->json(compact('posts')); return $this->json(compact('posts'));
} }
/** /**
* GET /api/v2/statuses/{id}/replies * GET /api/v2/statuses/{id}/replies
* *
* *
* @return array * @return array
*/ */
public function statusReplies(Request $request, $id) public function statusReplies(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'int|min:1|max:10', 'limit' => 'int|min:1|max:10',
@ -3707,14 +3781,15 @@ class ApiV1Controller extends Controller
} }
/** /**
* GET /api/v2/statuses/{id}/state * GET /api/v2/statuses/{id}/state
* *
* *
* @return array * @return array
*/ */
public function statusState(Request $request, $id) public function statusState(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
@ -3724,14 +3799,15 @@ class ApiV1Controller extends Controller
} }
/** /**
* GET /api/v1.1/discover/accounts/popular * GET /api/v1.1/discover/accounts/popular
* *
* *
* @return array * @return array
*/ */
public function discoverAccountsPopular(Request $request) public function discoverAccountsPopular(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
@ -3766,14 +3842,15 @@ class ApiV1Controller extends Controller
} }
/** /**
* GET /api/v1/preferences * GET /api/v1/preferences
* *
* *
* @return array * @return array
*/ */
public function getPreferences(Request $request) public function getPreferences(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$account = AccountService::get($pid); $account = AccountService::get($pid);
@ -3788,40 +3865,43 @@ class ApiV1Controller extends Controller
} }
/** /**
* GET /api/v1/trends * GET /api/v1/trends
* *
* *
* @return array * @return array
*/ */
public function getTrends(Request $request) public function getTrends(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return $this->json([]); return $this->json([]);
} }
/** /**
* GET /api/v1/announcements * GET /api/v1/announcements
* *
* *
* @return array * @return array
*/ */
public function getAnnouncements(Request $request) public function getAnnouncements(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
return $this->json([]); return $this->json([]);
} }
/** /**
* GET /api/v1/markers * GET /api/v1/markers
* *
* *
* @return array * @return array
*/ */
public function getMarkers(Request $request) public function getMarkers(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$type = $request->input('timeline'); $type = $request->input('timeline');
if(is_array($type)) { if(is_array($type)) {
@ -3835,14 +3915,15 @@ class ApiV1Controller extends Controller
} }
/** /**
* POST /api/v1/markers * POST /api/v1/markers
* *
* *
* @return array * @return array
*/ */
public function setMarkers(Request $request) public function setMarkers(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$home = $request->input('home[last_read_id]'); $home = $request->input('home[last_read_id]');

View file

@ -68,9 +68,10 @@ class ApiV1Dot1Controller extends Controller
public function report(Request $request) public function report(Request $request)
{ {
$user = $request->user(); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
abort_if(!$user, 403); $user = $request->user();
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
@ -175,9 +176,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function deleteAvatar(Request $request) public function deleteAvatar(Request $request)
{ {
$user = $request->user(); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
abort_if(!$user, 403); $user = $request->user();
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
@ -215,9 +217,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function accountPosts(Request $request, $id) public function accountPosts(Request $request, $id)
{ {
$user = $request->user(); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
abort_if(!$user, 403); $user = $request->user();
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
@ -255,8 +258,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function accountChangePassword(Request $request) public function accountChangePassword(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -296,8 +301,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function accountLoginActivity(Request $request) public function accountLoginActivity(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -336,8 +343,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function accountTwoFactor(Request $request) public function accountTwoFactor(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
@ -358,8 +367,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function accountEmailsFromPixelfed(Request $request) public function accountEmailsFromPixelfed(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -433,8 +444,10 @@ class ApiV1Dot1Controller extends Controller
*/ */
public function accountApps(Request $request) public function accountApps(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403); abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
@ -640,7 +653,8 @@ class ApiV1Dot1Controller extends Controller
public function archive(Request $request, $id) public function archive(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -672,7 +686,8 @@ class ApiV1Dot1Controller extends Controller
public function unarchive(Request $request, $id) public function unarchive(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -703,7 +718,8 @@ class ApiV1Dot1Controller extends Controller
public function archivedPosts(Request $request) public function archivedPosts(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -719,7 +735,8 @@ class ApiV1Dot1Controller extends Controller
public function placesById(Request $request, $id, $slug) public function placesById(Request $request, $id, $slug)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404); abort_if(BouncerService::checkIp($request->ip()), 404);
@ -865,7 +882,9 @@ class ApiV1Dot1Controller extends Controller
public function getWebSettings(Request $request) public function getWebSettings(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$uid = $request->user()->id; $uid = $request->user()->id;
$settings = UserSetting::firstOrCreate([ $settings = UserSetting::firstOrCreate([
'user_id' => $uid 'user_id' => $uid
@ -878,7 +897,9 @@ class ApiV1Dot1Controller extends Controller
public function setWebSettings(Request $request) public function setWebSettings(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'field' => 'required|in:enable_reblogs,hide_reblog_banner', 'field' => 'required|in:enable_reblogs,hide_reblog_banner',
'value' => 'required' 'value' => 'required'
@ -902,7 +923,9 @@ class ApiV1Dot1Controller extends Controller
public function getMutualAccounts(Request $request, $id) public function getMutualAccounts(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follows'), 403);
$account = AccountService::get($id, true); $account = AccountService::get($id, true);
if(!$account || !isset($account['id'])) { return []; } if(!$account || !isset($account['id'])) { return []; }
$res = collect(FollowerService::mutualAccounts($request->user()->profile_id, $id)) $res = collect(FollowerService::mutualAccounts($request->user()->profile_id, $id))

View file

@ -148,7 +148,8 @@ class ApiV2Controller extends Controller
*/ */
public function search(Request $request) public function search(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'q' => 'required|string|min:1|max:100', 'q' => 'required|string|min:1|max:100',
@ -199,7 +200,8 @@ class ApiV2Controller extends Controller
*/ */
public function mediaUploadV2(Request $request) public function mediaUploadV2(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'file.*' => [ 'file.*' => [

View file

@ -56,7 +56,8 @@ class BaseApiController extends Controller
public function notifications(Request $request) public function notifications(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$limit = $request->input('limit', 20); $limit = $request->input('limit', 20);
@ -98,7 +99,9 @@ class BaseApiController extends Controller
public function avatarUpdate(Request $request) public function avatarUpdate(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'upload' => 'required|mimetypes:image/jpeg,image/jpg,image/png|max:'.config('pixelfed.max_avatar_size'), 'upload' => 'required|mimetypes:image/jpeg,image/jpg,image/png|max:'.config('pixelfed.max_avatar_size'),
]); ]);
@ -134,9 +137,11 @@ class BaseApiController extends Controller
public function verifyCredentials(Request $request) public function verifyCredentials(Request $request)
{ {
abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$user = $request->user(); $user = $request->user();
abort_if(!$user, 403); if ($user->status != null) {
if($user->status != null) {
Auth::logout(); Auth::logout();
abort(403); abort(403);
} }
@ -146,7 +151,9 @@ class BaseApiController extends Controller
public function accountLikes(Request $request) public function accountLikes(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'page' => 'sometimes|int|min:1|max:20', 'page' => 'sometimes|int|min:1|max:20',
'limit' => 'sometimes|int|min:1|max:10' 'limit' => 'sometimes|int|min:1|max:10'
@ -173,7 +180,8 @@ class BaseApiController extends Controller
public function archive(Request $request, $id) public function archive(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$status = Status::whereNull('in_reply_to_id') $status = Status::whereNull('in_reply_to_id')
->whereNull('reblog_of_id') ->whereNull('reblog_of_id')
@ -201,7 +209,8 @@ class BaseApiController extends Controller
public function unarchive(Request $request, $id) public function unarchive(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$status = Status::whereNull('in_reply_to_id') $status = Status::whereNull('in_reply_to_id')
->whereNull('reblog_of_id') ->whereNull('reblog_of_id')
@ -228,7 +237,8 @@ class BaseApiController extends Controller
public function archivedPosts(Request $request) public function archivedPosts(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$statuses = Status::whereProfileId($request->user()->profile_id) $statuses = Status::whereProfileId($request->user()->profile_id)
->whereScope('archived') ->whereScope('archived')

View file

@ -23,7 +23,9 @@ class DomainBlockController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
abort_unless($request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$this->validate($request, [ $this->validate($request, [
'limit' => 'sometimes|integer|min:1|max:200' 'limit' => 'sometimes|integer|min:1|max:200'
]); ]);
@ -52,7 +54,8 @@ class DomainBlockController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
abort_unless($request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'domain' => 'required|active_url|min:1|max:120' 'domain' => 'required|active_url|min:1|max:120'
@ -99,7 +102,8 @@ class DomainBlockController extends Controller
public function delete(Request $request) public function delete(Request $request)
{ {
abort_unless($request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [ $this->validate($request, [
'domain' => 'required|min:1|max:120' 'domain' => 'required|min:1|max:120'

View file

@ -32,7 +32,9 @@ class TagsController extends Controller
*/ */
public function relatedTags(Request $request, $tag) public function relatedTags(Request $request, $tag)
{ {
abort_unless($request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$tag = Hashtag::whereSlug($tag)->firstOrFail(); $tag = Hashtag::whereSlug($tag)->firstOrFail();
return HashtagRelatedService::get($tag->id); return HashtagRelatedService::get($tag->id);
} }
@ -45,7 +47,8 @@ class TagsController extends Controller
*/ */
public function followHashtag(Request $request, $id) public function followHashtag(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follow'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$account = AccountService::get($pid); $account = AccountService::get($pid);
@ -87,7 +90,8 @@ class TagsController extends Controller
*/ */
public function unfollowHashtag(Request $request, $id) public function unfollowHashtag(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('follow'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$account = AccountService::get($pid); $account = AccountService::get($pid);
@ -132,7 +136,8 @@ class TagsController extends Controller
*/ */
public function getHashtag(Request $request, $id) public function getHashtag(Request $request, $id)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$account = AccountService::get($pid); $account = AccountService::get($pid);
@ -172,7 +177,8 @@ class TagsController extends Controller
*/ */
public function getFollowedTags(Request $request) public function getFollowedTags(Request $request)
{ {
abort_if(!$request->user(), 403); abort_if(!$request->user() || !$request->user()->token(), 403);
abort_unless($request->user()->tokenCan('read'), 403);
$account = AccountService::get($request->user()->profile_id); $account = AccountService::get($request->user()->profile_id);