@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Only require view permissions for read-only Git LFS requests

Summary: Ref T7789. Implement proper detection for read-only requests. Previously, we assumed every request was read/write and required lots of permissions, but we don't need "Can Push" permission if you're only cloning/fetching/pulling.

Test Plan:
- Set push policy to "no one".
- Fetched, got clean data out of LFS.
- Tried to push, got useful error.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T7789

Differential Revision: https://secure.phabricator.com/D15499

+55 -8
+55 -8
src/applications/diffusion/controller/DiffusionServeController.php
··· 7 7 8 8 private $isGitLFSRequest; 9 9 private $gitLFSToken; 10 + private $gitLFSInput; 10 11 11 12 public function setServiceViewer(PhabricatorUser $viewer) { 12 13 $this->getRequest()->setUser($viewer); ··· 284 285 DiffusionPushCapability::CAPABILITY); 285 286 if (!$can_push) { 286 287 if ($viewer->isLoggedIn()) { 287 - return new PhabricatorVCSResponse( 288 - 403, 289 - pht( 290 - 'You do not have permission to push to this '. 291 - 'repository.')); 288 + $error_code = 403; 289 + $error_message = pht( 290 + 'You do not have permission to push to this repository ("%s").', 291 + $repository->getDisplayName()); 292 + 293 + if ($this->getIsGitLFSRequest()) { 294 + return DiffusionGitLFSResponse::newErrorResponse( 295 + $error_code, 296 + $error_message); 297 + } else { 298 + return new PhabricatorVCSResponse( 299 + $error_code, 300 + $error_message); 301 + } 292 302 } else { 293 303 if ($allow_auth) { 294 304 return new PhabricatorVCSResponse( ··· 422 432 423 433 // TODO: This implementation is safe by default, but very incomplete. 424 434 425 - // TODO: This doesn't get the right result for Git LFS yet. 435 + if ($this->getIsGitLFSRequest()) { 436 + return $this->isGitLFSReadOnlyRequest($repository); 437 + } 426 438 427 439 switch ($repository->getVersionControlSystem()) { 428 440 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: ··· 911 923 PhabricatorRepository $repository, 912 924 PhabricatorUser $viewer) { 913 925 914 - $input = PhabricatorStartup::getRawInput(); 915 - $input = phutil_json_decode($input); 926 + $input = $this->getGitLFSInput(); 916 927 917 928 $operation = idx($input, 'operation'); 918 929 switch ($operation) { ··· 1061 1072 $oid)); 1062 1073 } 1063 1074 1075 + // Remove the execution time limit because uploading large files may take 1076 + // a while. 1077 + set_time_limit(0); 1078 + 1064 1079 $request_stream = new AphrontRequestStream(); 1065 1080 $request_iterator = $request_stream->getIterator(); 1066 1081 $hashing_iterator = id(new PhutilHashingIterator($request_iterator)) ··· 1132 1147 1133 1148 return null; 1134 1149 } 1150 + 1151 + private function getGitLFSInput() { 1152 + if (!$this->gitLFSInput) { 1153 + $input = PhabricatorStartup::getRawInput(); 1154 + $input = phutil_json_decode($input); 1155 + $this->gitLFSInput = $input; 1156 + } 1157 + 1158 + return $this->gitLFSInput; 1159 + } 1160 + 1161 + private function isGitLFSReadOnlyRequest(PhabricatorRepository $repository) { 1162 + if (!$this->getIsGitLFSRequest()) { 1163 + return false; 1164 + } 1165 + 1166 + $path = $this->getGitLFSRequestPath($repository); 1167 + 1168 + if ($path === 'objects/batch') { 1169 + $input = $this->getGitLFSInput(); 1170 + $operation = idx($input, 'operation'); 1171 + switch ($operation) { 1172 + case 'download': 1173 + return true; 1174 + default: 1175 + return false; 1176 + } 1177 + } 1178 + 1179 + return false; 1180 + } 1181 + 1135 1182 1136 1183 }