@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<?php
2
3final class ConduitGetCertificateConduitAPIMethod extends ConduitAPIMethod {
4
5 public function getAPIMethodName() {
6 return 'conduit.getcertificate';
7 }
8
9 public function shouldRequireAuthentication() {
10 return false;
11 }
12
13 public function shouldAllowUnguardedWrites() {
14 // This method performs logging and is on the authentication pathway.
15 return true;
16 }
17
18 public function getMethodStatus() {
19 return self::METHOD_STATUS_DEPRECATED;
20 }
21
22 public function getMethodStatusDescription() {
23 return pht(
24 'This method has been deprecated since %s in favor of token-based '.
25 'authentication.',
26 '02/2026');
27 }
28
29 public function getMethodDescription() {
30 return pht('Retrieve certificate information for a user.');
31 }
32
33 protected function defineParamTypes() {
34 return array(
35 'token' => 'required string',
36 'host' => 'required string',
37 );
38 }
39
40 protected function defineReturnType() {
41 return 'dict<string, any>';
42 }
43
44 protected function defineErrorTypes() {
45 return array(
46 'ERR-BAD-TOKEN' => pht('Token does not exist or has expired.'),
47 'ERR-RATE-LIMIT' => pht(
48 'You have made too many invalid token requests recently. Wait before '.
49 'making more.'),
50 );
51 }
52
53 protected function execute(ConduitAPIRequest $request) {
54 $failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP(
55 PhabricatorConduitCertificateFailureUserLogType::LOGTYPE,
56 60 * 5);
57
58 if (count($failed_attempts) > 5) {
59 $this->logFailure($request);
60 throw new ConduitException('ERR-RATE-LIMIT');
61 }
62
63 $info = null;
64 $token = $request->getValue('token');
65 if ($token !== null) {
66 $info = id(new PhabricatorConduitCertificateToken())->loadOneWhere(
67 'token = %s',
68 trim($token));
69 }
70
71 if (!$info || $info->getDateCreated() < time() - (60 * 15)) {
72 $this->logFailure($request, $info);
73 throw new ConduitException('ERR-BAD-TOKEN');
74 } else {
75 $log = PhabricatorUserLog::initializeNewLog(
76 $request->getUser(),
77 $info->getUserPHID(),
78 PhabricatorConduitCertificateUserLogType::LOGTYPE)
79 ->save();
80 }
81
82 $user = id(new PhabricatorUser())->loadOneWhere(
83 'phid = %s',
84 $info->getUserPHID());
85 if (!$user) {
86 throw new Exception(pht('Certificate token points to an invalid user!'));
87 }
88
89 return array(
90 'username' => $user->getUserName(),
91 'certificate' => $user->getConduitCertificate(),
92 );
93 }
94
95 private function logFailure(
96 ConduitAPIRequest $request,
97 ?PhabricatorConduitCertificateToken $info = null) {
98
99 $log = PhabricatorUserLog::initializeNewLog(
100 $request->getUser(),
101 $info ? $info->getUserPHID() : '-',
102 PhabricatorConduitCertificateFailureUserLogType::LOGTYPE)
103 ->save();
104 }
105
106}