From 7b0a6060b2053eb18a02758288280b7b0de6e3e3 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Thu, 8 Feb 2024 02:49:35 +0100 Subject: [PATCH 01/10] Return access tokens' scopes, not hardcoded list --- app/Auth/BearerTokenResponse.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Auth/BearerTokenResponse.php b/app/Auth/BearerTokenResponse.php index 79cd97c85..a3175d798 100644 --- a/app/Auth/BearerTokenResponse.php +++ b/app/Auth/BearerTokenResponse.php @@ -18,8 +18,8 @@ class BearerTokenResponse extends \League\OAuth2\Server\ResponseTypes\BearerToke protected function getExtraParams(AccessTokenEntityInterface $accessToken) { return [ - 'created_at' => time(), - 'scope' => 'read write follow push' + 'created_at' => time(), + 'scope' => implode(' ', $accessToken->getScopes()) ]; } } From 9330cd02f7c05fe3f4ade786e8429fb804a93cb2 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Thu, 8 Feb 2024 02:50:02 +0100 Subject: [PATCH 02/10] Implement proper OAuth authorization on Admin API endpoints --- .../Controllers/Api/AdminApiController.php | 67 ++++++++++++++----- .../Controllers/Api/ApiV1Dot1Controller.php | 3 +- app/Providers/AuthServiceProvider.php | 4 +- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/app/Http/Controllers/Api/AdminApiController.php b/app/Http/Controllers/Api/AdminApiController.php index 76f73e720..69ba54cee 100644 --- a/app/Http/Controllers/Api/AdminApiController.php +++ b/app/Http/Controllers/Api/AdminApiController.php @@ -40,16 +40,20 @@ class AdminApiController extends Controller { public function supported(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); return response()->json(['supported' => true]); } public function getStats(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); $res = AdminStatsService::summary(); $res['autospam_count'] = AccountInterstitial::whereType('post.autospam') @@ -60,8 +64,10 @@ class AdminApiController extends Controller public function autospam(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); $appeals = AccountInterstitial::whereType('post.autospam') ->whereNull('appeal_handled_at') @@ -95,8 +101,10 @@ class AdminApiController extends Controller public function autospamHandle(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); $this->validate($request, [ 'action' => 'required|in:dismiss,approve,dismiss-all,approve-all,delete-post,delete-account', @@ -239,8 +247,10 @@ class AdminApiController extends Controller public function modReports(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); $reports = Report::whereNull('admin_seen') ->orderBy('created_at','desc') @@ -285,8 +295,10 @@ class AdminApiController extends Controller public function modReportHandle(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); $this->validate($request, [ 'action' => 'required|string', @@ -343,8 +355,11 @@ class AdminApiController extends Controller public function getConfiguration(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); + abort_unless(config('instance.enable_cc'), 400); return collect([ @@ -386,8 +401,11 @@ class AdminApiController extends Controller public function updateConfiguration(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); + abort_unless(config('instance.enable_cc'), 400); $this->validate($request, [ @@ -448,8 +466,11 @@ class AdminApiController extends Controller public function getUsers(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); + $this->validate($request, [ 'sort' => 'sometimes|in:asc,desc', ]); @@ -466,8 +487,10 @@ class AdminApiController extends Controller public function getUser(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); $id = $request->input('user_id'); $key = 'pf-admin-api:getUser:byId:' . $id; @@ -497,8 +520,10 @@ class AdminApiController extends Controller public function userAdminAction(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); $this->validate($request, [ 'id' => 'required', @@ -669,8 +694,10 @@ class AdminApiController extends Controller public function instances(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); $this->validate($request, [ 'q' => 'sometimes', @@ -707,8 +734,10 @@ class AdminApiController extends Controller public function getInstance(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); $id = $request->input('id'); $res = Instance::findOrFail($id); @@ -718,8 +747,10 @@ class AdminApiController extends Controller public function moderateInstance(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); $this->validate($request, [ 'id' => 'required', @@ -742,8 +773,10 @@ class AdminApiController extends Controller public function refreshInstanceStats(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin == 1, 404); + abort_unless($request->user()->tokenCan('admin:write'), 404); $this->validate($request, [ 'id' => 'required', @@ -760,8 +793,10 @@ class AdminApiController extends Controller public function getAllStats(Request $request) { - abort_if(!$request->user(), 404); + abort_if(!$request->user() || !$request->user()->token(), 404); + abort_unless($request->user()->is_admin === 1, 404); + abort_unless($request->user()->tokenCan('admin:read'), 404); if($request->has('refresh')) { Cache::forget('admin-api:instance-all-stats-v1'); diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 75d0fe984..22aa40c9b 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -757,8 +757,9 @@ class ApiV1Dot1Controller extends Controller public function moderatePost(Request $request, $id) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); abort_if($request->user()->is_admin != true, 403); + abort_unless($request->user()->tokenCan('admin:write'), 403); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { abort_if(BouncerService::checkIp($request->ip()), 404); diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 8e1a6a98d..34d25ac76 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -41,7 +41,9 @@ class AuthServiceProvider extends ServiceProvider 'read' => 'Full read access to your account', 'write' => 'Full write access to your account', 'follow' => 'Ability to follow other profiles', - 'push' => '' + 'admin:read' => 'Read all data on the server', + 'admin:write' => 'Modify all data on the server', + 'push' => 'Receive your push notifications' ]); } From 0f8e45fe7588bd50eac26c731f9ebd87449f6cdf Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Thu, 8 Feb 2024 02:48:17 +0100 Subject: [PATCH 03/10] Implement proper OAuth authorization on API endpoints --- app/Http/Controllers/Api/ApiV1Controller.php | 295 +++++++++++------- .../Controllers/Api/ApiV1Dot1Controller.php | 59 ++-- app/Http/Controllers/Api/ApiV2Controller.php | 6 +- .../Controllers/Api/BaseApiController.php | 26 +- .../Api/V1/DomainBlockController.php | 10 +- .../Controllers/Api/V1/TagsController.php | 16 +- 6 files changed, 269 insertions(+), 143 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index b94a11c92..50e9eacc5 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -125,11 +125,15 @@ class ApiV1Controller extends Controller return response()->json($res, $code, $headers, JSON_UNESCAPED_SLASHES); } + /** + * GET /api/v1/apps/verify_credentials + */ public function getApp(Request $request) { - if(!$request->user()) { - return response('', 403); - } + # FIXME: /api/v1/apps/verify_credentials should be accessible with any + # 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; $res = [ @@ -141,6 +145,9 @@ class ApiV1Controller extends Controller return $this->json($res); } + /** + * POST /api/v1/apps + */ public function apps(Request $request) { abort_if(!config_cache('pixelfed.oauth_enabled'), 404); @@ -187,9 +194,11 @@ class ApiV1Controller extends Controller */ public function verifyCredentials(Request $request) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); - abort_if(!$user, 403); abort_if($user->status != null, 403); AccountService::setLastActive($user->id); @@ -215,6 +224,9 @@ class ApiV1Controller extends Controller */ 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); if(!$res) { return response()->json(['error' => 'Record not found'], 404); @@ -233,7 +245,8 @@ class ApiV1Controller extends Controller */ 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')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -476,7 +489,8 @@ class ApiV1Controller extends Controller */ 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); abort_if(!$account, 404); @@ -573,7 +587,8 @@ class ApiV1Controller extends Controller */ 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); abort_if(!$account, 404); @@ -670,6 +685,9 @@ class ApiV1Controller extends Controller */ public function accountStatusesById(Request $request, $id) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); $this->validate($request, [ @@ -774,7 +792,8 @@ class ApiV1Controller extends Controller */ 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(); 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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('follow'), 403); $user = $request->user(); @@ -936,7 +956,8 @@ class ApiV1Controller extends Controller */ 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, [ 'id' => 'required|array|min:1|max:20', @@ -965,7 +986,8 @@ class ApiV1Controller extends Controller */ 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, [ 'q' => 'required|string|min:1|max:255', @@ -1008,7 +1030,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'nullable|integer|min:1|max:40', @@ -1045,7 +1068,8 @@ class ApiV1Controller extends Controller */ 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(); $pid = $user->profile_id ?? $user->profile->id; @@ -1138,7 +1162,8 @@ class ApiV1Controller extends Controller */ 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(); $pid = $user->profile_id ?? $user->profile->id; @@ -1189,7 +1214,9 @@ class ApiV1Controller extends Controller */ 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([]); } @@ -1202,7 +1229,9 @@ class ApiV1Controller extends Controller */ 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([]); } @@ -1215,7 +1244,9 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'sometimes|integer|min:1|max:40' ]); @@ -1271,7 +1302,8 @@ class ApiV1Controller extends Controller */ 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(); 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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('write'), 403); $user = $request->user(); 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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); return response()->json([]); } @@ -1395,7 +1429,9 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'sometimes|integer|min:1|max:100' ]); @@ -1425,7 +1461,9 @@ class ApiV1Controller extends Controller */ 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; $target = AccountService::getMastodon($id); @@ -1482,7 +1520,9 @@ class ApiV1Controller extends Controller */ 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; $target = AccountService::getMastodon($id); @@ -1518,7 +1558,8 @@ class ApiV1Controller extends Controller */ 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 @@ -1619,7 +1660,8 @@ class ApiV1Controller extends Controller */ 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([]); } @@ -1633,7 +1675,8 @@ class ApiV1Controller extends Controller */ 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([]); } @@ -1646,7 +1689,8 @@ class ApiV1Controller extends Controller */ 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, [ 'file.*' => [ @@ -1782,7 +1826,8 @@ class ApiV1Controller extends Controller */ 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, [ 'description' => 'nullable|string|max:' . config_cache('pixelfed.max_altext_length') @@ -1835,7 +1880,8 @@ class ApiV1Controller extends Controller */ 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(); 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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('write'), 403); $this->validate($request, [ 'file.*' => [ @@ -1999,7 +2046,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'nullable|integer|min:1|max:40' @@ -2034,7 +2082,8 @@ class ApiV1Controller extends Controller */ 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(); $pid = $user->profile_id; @@ -2092,7 +2141,8 @@ class ApiV1Controller extends Controller */ 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(); $pid = $user->profile_id; @@ -2128,7 +2178,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'nullable|integer|min:1|max:100', @@ -2204,7 +2255,10 @@ class ApiV1Controller extends Controller */ 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', 'min_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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $this->validate($request, [ 'limit' => 'min:1|max:40', 'scope' => 'nullable|in:inbox,sent,requests' @@ -2683,7 +2739,9 @@ class ApiV1Controller extends Controller */ 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); $pid = $request->user()->profile_id; @@ -2730,7 +2788,8 @@ class ApiV1Controller extends Controller */ 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(); AccountService::setLastActive($user->id); @@ -2803,7 +2862,9 @@ class ApiV1Controller extends Controller */ 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 = []; return response()->json($res); } @@ -2817,7 +2878,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'sometimes|integer|min:1|max:80' @@ -2913,7 +2975,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'nullable|integer|min:1|max:80' @@ -3010,7 +3073,8 @@ class ApiV1Controller extends Controller */ 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, [ 'status' => 'nullable|string', @@ -3225,7 +3289,9 @@ class ApiV1Controller extends Controller */ 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); $status = Status::whereProfileId($request->user()->profile->id) ->findOrFail($id); @@ -3251,7 +3317,8 @@ class ApiV1Controller extends Controller */ 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(); 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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('write'), 403); $user = $request->user(); 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) { - abort_if(!$request->user(), 403); + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); $this->validate($request,[ 'page' => 'nullable|integer|max:40', @@ -3447,7 +3516,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'nullable|integer|min:1|max:40', @@ -3514,7 +3584,8 @@ class ApiV1Controller extends Controller */ 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); $pid = $request->user()->profile_id; @@ -3554,7 +3625,8 @@ class ApiV1Controller extends Controller */ 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); $pid = $request->user()->profile_id; @@ -3586,7 +3658,8 @@ class ApiV1Controller extends Controller */ 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, [ 'limit' => 'integer|min:1|max:40' @@ -3596,29 +3669,30 @@ class ApiV1Controller extends Controller $pid = $request->user()->profile_id; $filters = UserFilterService::filters($pid); $forYou = DiscoverService::getForYou(); - $posts = $forYou->take(50)->map(function($post) { + $posts = $forYou->take(50)->map(function ($post) { return StatusService::getMastodon($post); }) - ->filter(function($post) use($filters) { - return $post && - isset($post['account']) && - isset($post['account']['id']) && - !in_array($post['account']['id'], $filters); - }) - ->take(12) - ->values(); + ->filter(function ($post) use ($filters) { + return $post && + isset($post['account']) && + isset($post['account']['id']) && + !in_array($post['account']['id'], $filters); + }) + ->take(12) + ->values(); return $this->json(compact('posts')); } /** - * GET /api/v2/statuses/{id}/replies - * - * - * @return array - */ + * GET /api/v2/statuses/{id}/replies + * + * + * @return array + */ 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, [ 'limit' => 'int|min:1|max:10', @@ -3707,14 +3781,15 @@ class ApiV1Controller extends Controller } /** - * GET /api/v2/statuses/{id}/state - * - * - * @return array - */ + * GET /api/v2/statuses/{id}/state + * + * + * @return array + */ 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); $pid = $request->user()->profile_id; @@ -3724,14 +3799,15 @@ class ApiV1Controller extends Controller } /** - * GET /api/v1.1/discover/accounts/popular - * - * - * @return array - */ + * GET /api/v1.1/discover/accounts/popular + * + * + * @return array + */ 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; @@ -3766,14 +3842,15 @@ class ApiV1Controller extends Controller } /** - * GET /api/v1/preferences - * - * - * @return array - */ + * GET /api/v1/preferences + * + * + * @return array + */ 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; $account = AccountService::get($pid); @@ -3788,40 +3865,43 @@ class ApiV1Controller extends Controller } /** - * GET /api/v1/trends - * - * - * @return array - */ + * GET /api/v1/trends + * + * + * @return array + */ 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([]); } /** - * GET /api/v1/announcements - * - * - * @return array - */ + * GET /api/v1/announcements + * + * + * @return array + */ 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([]); } /** - * GET /api/v1/markers - * - * - * @return array - */ + * GET /api/v1/markers + * + * + * @return array + */ 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'); if(is_array($type)) { @@ -3835,14 +3915,15 @@ class ApiV1Controller extends Controller } /** - * POST /api/v1/markers - * - * - * @return array - */ + * POST /api/v1/markers + * + * + * @return array + */ 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; $home = $request->input('home[last_read_id]'); diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 22aa40c9b..c34b9d968 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -68,9 +68,10 @@ class ApiV1Dot1Controller extends Controller 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); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { @@ -175,9 +176,10 @@ class ApiV1Dot1Controller extends Controller */ 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); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { @@ -215,9 +217,10 @@ class ApiV1Dot1Controller extends Controller */ 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); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { @@ -255,8 +258,10 @@ class ApiV1Dot1Controller extends Controller */ public function accountChangePassword(Request $request) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('write'), 403); + $user = $request->user(); - abort_if(!$user, 403); abort_if($user->status != null, 403); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -296,8 +301,10 @@ class ApiV1Dot1Controller extends Controller */ public function accountLoginActivity(Request $request) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); - abort_if(!$user, 403); abort_if($user->status != null, 403); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -336,8 +343,10 @@ class ApiV1Dot1Controller extends Controller */ public function accountTwoFactor(Request $request) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); - abort_if(!$user, 403); abort_if($user->status != null, 403); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { @@ -358,8 +367,10 @@ class ApiV1Dot1Controller extends Controller */ public function accountEmailsFromPixelfed(Request $request) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); - abort_if(!$user, 403); abort_if($user->status != null, 403); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -433,8 +444,10 @@ class ApiV1Dot1Controller extends Controller */ public function accountApps(Request $request) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); - abort_if(!$user, 403); abort_if($user->status != null, 403); if(config('pixelfed.bouncer.cloud_ips.ban_signups')) { @@ -640,7 +653,8 @@ class ApiV1Dot1Controller extends Controller 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')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -672,7 +686,8 @@ class ApiV1Dot1Controller extends Controller 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')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -703,7 +718,8 @@ class ApiV1Dot1Controller extends Controller 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')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -719,7 +735,8 @@ class ApiV1Dot1Controller extends Controller 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')) { abort_if(BouncerService::checkIp($request->ip()), 404); @@ -865,7 +882,9 @@ class ApiV1Dot1Controller extends Controller 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; $settings = UserSetting::firstOrCreate([ 'user_id' => $uid @@ -878,7 +897,9 @@ class ApiV1Dot1Controller extends Controller 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, [ 'field' => 'required|in:enable_reblogs,hide_reblog_banner', 'value' => 'required' @@ -902,7 +923,9 @@ class ApiV1Dot1Controller extends Controller 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); if(!$account || !isset($account['id'])) { return []; } $res = collect(FollowerService::mutualAccounts($request->user()->profile_id, $id)) diff --git a/app/Http/Controllers/Api/ApiV2Controller.php b/app/Http/Controllers/Api/ApiV2Controller.php index ce15a8a49..2380588cf 100644 --- a/app/Http/Controllers/Api/ApiV2Controller.php +++ b/app/Http/Controllers/Api/ApiV2Controller.php @@ -148,7 +148,8 @@ class ApiV2Controller extends Controller */ 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, [ 'q' => 'required|string|min:1|max:100', @@ -199,7 +200,8 @@ class ApiV2Controller extends Controller */ 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, [ 'file.*' => [ diff --git a/app/Http/Controllers/Api/BaseApiController.php b/app/Http/Controllers/Api/BaseApiController.php index 2e1fb5678..72e7f1574 100644 --- a/app/Http/Controllers/Api/BaseApiController.php +++ b/app/Http/Controllers/Api/BaseApiController.php @@ -56,7 +56,8 @@ class BaseApiController extends Controller 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; $limit = $request->input('limit', 20); @@ -98,7 +99,9 @@ class BaseApiController extends Controller 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, [ '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) { + abort_if(!$request->user() || !$request->user()->token(), 403); + abort_unless($request->user()->tokenCan('read'), 403); + $user = $request->user(); - abort_if(!$user, 403); - if($user->status != null) { + if ($user->status != null) { Auth::logout(); abort(403); } @@ -146,7 +151,9 @@ class BaseApiController extends Controller 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, [ 'page' => 'sometimes|int|min:1|max:20', 'limit' => 'sometimes|int|min:1|max:10' @@ -173,7 +180,8 @@ class BaseApiController extends Controller 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') ->whereNull('reblog_of_id') @@ -201,7 +209,8 @@ class BaseApiController extends Controller 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') ->whereNull('reblog_of_id') @@ -228,7 +237,8 @@ class BaseApiController extends Controller 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) ->whereScope('archived') diff --git a/app/Http/Controllers/Api/V1/DomainBlockController.php b/app/Http/Controllers/Api/V1/DomainBlockController.php index 2186c0936..3a4a4c793 100644 --- a/app/Http/Controllers/Api/V1/DomainBlockController.php +++ b/app/Http/Controllers/Api/V1/DomainBlockController.php @@ -23,7 +23,9 @@ class DomainBlockController extends Controller 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, [ 'limit' => 'sometimes|integer|min:1|max:200' ]); @@ -52,7 +54,8 @@ class DomainBlockController extends Controller 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, [ 'domain' => 'required|active_url|min:1|max:120' @@ -99,7 +102,8 @@ class DomainBlockController extends Controller 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, [ 'domain' => 'required|min:1|max:120' diff --git a/app/Http/Controllers/Api/V1/TagsController.php b/app/Http/Controllers/Api/V1/TagsController.php index 7314ce09d..5226b67ed 100644 --- a/app/Http/Controllers/Api/V1/TagsController.php +++ b/app/Http/Controllers/Api/V1/TagsController.php @@ -32,7 +32,9 @@ class TagsController extends Controller */ 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(); return HashtagRelatedService::get($tag->id); } @@ -45,7 +47,8 @@ class TagsController extends Controller */ 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; $account = AccountService::get($pid); @@ -87,7 +90,8 @@ class TagsController extends Controller */ 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; $account = AccountService::get($pid); @@ -132,7 +136,8 @@ class TagsController extends Controller */ 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; $account = AccountService::get($pid); @@ -172,7 +177,8 @@ class TagsController extends Controller */ 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); From 2e6100f2758fc6e18fb6b84d5efc71643e81a2bd Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:04:15 -0700 Subject: [PATCH 04/10] Update BearerTokenResponse, fix scope bug --- app/Auth/BearerTokenResponse.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Auth/BearerTokenResponse.php b/app/Auth/BearerTokenResponse.php index a3175d798..0e1aa8a19 100644 --- a/app/Auth/BearerTokenResponse.php +++ b/app/Auth/BearerTokenResponse.php @@ -19,7 +19,6 @@ class BearerTokenResponse extends \League\OAuth2\Server\ResponseTypes\BearerToke { return [ 'created_at' => time(), - 'scope' => implode(' ', $accessToken->getScopes()) ]; } } From 607b239c1a930d6858718152b35db508d8f5bf7c Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:05:22 -0700 Subject: [PATCH 05/10] Bump version to v0.11.10 --- CHANGELOG.md | 4 +++- config/pixelfed.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d939ea1e0..b61cdd706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Release Notes -## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.9...dev) +## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.10...dev) + +## [v0.11.10 (2024-02-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.9...v0.11.10) ### Added - Resilient Media Storage ([#4665](https://github.com/pixelfed/pixelfed/pull/4665)) ([fb1deb6](https://github.com/pixelfed/pixelfed/commit/fb1deb6)) diff --git a/config/pixelfed.php b/config/pixelfed.php index fc7da598a..3fe962513 100644 --- a/config/pixelfed.php +++ b/config/pixelfed.php @@ -23,7 +23,7 @@ return [ | This value is the version of your Pixelfed instance. | */ - 'version' => '0.11.9', + 'version' => '0.11.10', /* |-------------------------------------------------------------------------- From e354750808792fa258eec6f799f8e2ba3ea45d73 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:41:12 -0700 Subject: [PATCH 06/10] Fix api endpoints --- .../Controllers/Api/BaseApiController.php | 21 +++++++------------ .../Api/V1/DomainBlockController.php | 9 +++----- .../Controllers/Api/V1/TagsController.php | 12 ++++------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/app/Http/Controllers/Api/BaseApiController.php b/app/Http/Controllers/Api/BaseApiController.php index 72e7f1574..7ac73b4d0 100644 --- a/app/Http/Controllers/Api/BaseApiController.php +++ b/app/Http/Controllers/Api/BaseApiController.php @@ -56,8 +56,7 @@ class BaseApiController extends Controller public function notifications(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $pid = $request->user()->profile_id; $limit = $request->input('limit', 20); @@ -99,8 +98,7 @@ class BaseApiController extends Controller public function avatarUpdate(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('write'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'upload' => 'required|mimetypes:image/jpeg,image/jpg,image/png|max:'.config('pixelfed.max_avatar_size'), @@ -137,8 +135,7 @@ class BaseApiController extends Controller public function verifyCredentials(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $user = $request->user(); if ($user->status != null) { @@ -151,8 +148,7 @@ class BaseApiController extends Controller public function accountLikes(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'page' => 'sometimes|int|min:1|max:20', @@ -180,8 +176,7 @@ class BaseApiController extends Controller public function archive(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('write'), 403); + abort_if(!$request->user(), 403); $status = Status::whereNull('in_reply_to_id') ->whereNull('reblog_of_id') @@ -209,8 +204,7 @@ class BaseApiController extends Controller public function unarchive(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('write'), 403); + abort_if(!$request->user(), 403); $status = Status::whereNull('in_reply_to_id') ->whereNull('reblog_of_id') @@ -237,8 +231,7 @@ class BaseApiController extends Controller public function archivedPosts(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $statuses = Status::whereProfileId($request->user()->profile_id) ->whereScope('archived') diff --git a/app/Http/Controllers/Api/V1/DomainBlockController.php b/app/Http/Controllers/Api/V1/DomainBlockController.php index 3a4a4c793..5a2698361 100644 --- a/app/Http/Controllers/Api/V1/DomainBlockController.php +++ b/app/Http/Controllers/Api/V1/DomainBlockController.php @@ -23,8 +23,7 @@ class DomainBlockController extends Controller public function index(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'limit' => 'sometimes|integer|min:1|max:200' @@ -54,8 +53,7 @@ class DomainBlockController extends Controller public function store(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('write'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'domain' => 'required|active_url|min:1|max:120' @@ -102,8 +100,7 @@ class DomainBlockController extends Controller public function delete(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('write'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'domain' => 'required|min:1|max:120' diff --git a/app/Http/Controllers/Api/V1/TagsController.php b/app/Http/Controllers/Api/V1/TagsController.php index 5226b67ed..2f7acf4a0 100644 --- a/app/Http/Controllers/Api/V1/TagsController.php +++ b/app/Http/Controllers/Api/V1/TagsController.php @@ -47,8 +47,7 @@ class TagsController extends Controller */ public function followHashtag(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('follow'), 403); + abort_if(!$request->user(), 403); $pid = $request->user()->profile_id; $account = AccountService::get($pid); @@ -90,8 +89,7 @@ class TagsController extends Controller */ public function unfollowHashtag(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('follow'), 403); + abort_if(!$request->user(), 403); $pid = $request->user()->profile_id; $account = AccountService::get($pid); @@ -136,8 +134,7 @@ class TagsController extends Controller */ public function getHashtag(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $pid = $request->user()->profile_id; $account = AccountService::get($pid); @@ -177,8 +174,7 @@ class TagsController extends Controller */ public function getFollowedTags(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $account = AccountService::get($request->user()->profile_id); From fd7f5dbba13818f60d1c2b3ab110b499e996aa81 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:45:10 -0700 Subject: [PATCH 07/10] Fix api endpoints --- app/Http/Controllers/Api/ApiV1Controller.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 50e9eacc5..8ae65eb44 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -3691,8 +3691,7 @@ class ApiV1Controller extends Controller */ public function statusReplies(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'limit' => 'int|min:1|max:10', @@ -3788,8 +3787,7 @@ class ApiV1Controller extends Controller */ public function statusState(Request $request, $id) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $status = Status::findOrFail($id); $pid = $request->user()->profile_id; From 62b9eef8056f737086352c790fede60cb081c041 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:51:37 -0700 Subject: [PATCH 08/10] Fix api endpoints --- app/Http/Controllers/Api/ApiV1Controller.php | 3 +-- app/Http/Controllers/ComposeController.php | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 8ae65eb44..d1bd9cac2 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -956,8 +956,7 @@ class ApiV1Controller extends Controller */ public function accountRelationshipsById(Request $request) { - abort_if(!$request->user() || !$request->user()->token(), 403); - abort_unless($request->user()->tokenCan('read'), 403); + abort_if(!$request->user(), 403); $this->validate($request, [ 'id' => 'required|array|min:1|max:20', diff --git a/app/Http/Controllers/ComposeController.php b/app/Http/Controllers/ComposeController.php index e17a37fd7..36bd5a66c 100644 --- a/app/Http/Controllers/ComposeController.php +++ b/app/Http/Controllers/ComposeController.php @@ -260,6 +260,8 @@ class ComposeController extends Controller $q = mb_substr($q, 1); } + $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); $blocked = UserFilter::whereFilterableType('App\Profile') From 7a7b4bc717c47b37bcad447a95bb0e00c2a68d26 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:54:17 -0700 Subject: [PATCH 09/10] Update AuthServiceProvider --- app/Providers/AuthServiceProvider.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 34d25ac76..52e992ce0 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -31,11 +31,6 @@ class AuthServiceProvider extends ServiceProvider if(config('instance.oauth.pat.enabled')) { Passport::personalAccessClientId(config('instance.oauth.pat.id')); } - Passport::setDefaultScope([ - 'read', - 'write', - 'follow', - ]); Passport::tokensCan([ 'read' => 'Full read access to your account', @@ -45,6 +40,12 @@ class AuthServiceProvider extends ServiceProvider 'admin:write' => 'Modify all data on the server', 'push' => 'Receive your push notifications' ]); + + Passport::setDefaultScope([ + 'read', + 'write', + 'follow', + ]); } // Gate::define('viewWebSocketsDashboard', function ($user = null) { From e5bbe9340a33df98a0941cb31b854bcef3638b1f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 9 Feb 2024 20:57:45 -0700 Subject: [PATCH 10/10] Bump version to v0.11.11 --- CHANGELOG.md | 7 ++++++- config/pixelfed.php | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b61cdd706..de5f73b61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Release Notes -## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.10...dev) +## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.11...dev) + +## [v0.11.11 (2024-02-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.10...v0.11.11) + +### Fixes +- Fix api endpoints ([fd7f5dbb](https://github.com/pixelfed/pixelfed/commit/fd7f5dbb)) ## [v0.11.10 (2024-02-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.9...v0.11.10) diff --git a/config/pixelfed.php b/config/pixelfed.php index 3fe962513..9ed7fc616 100644 --- a/config/pixelfed.php +++ b/config/pixelfed.php @@ -23,7 +23,7 @@ return [ | This value is the version of your Pixelfed instance. | */ - 'version' => '0.11.10', + 'version' => '0.11.11', /* |--------------------------------------------------------------------------