Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/conduit/storage/PhabricatorConduitToken.php
12256 views
1
<?php
2
3
final class PhabricatorConduitToken
4
extends PhabricatorConduitDAO
5
implements PhabricatorPolicyInterface {
6
7
protected $objectPHID;
8
protected $tokenType;
9
protected $token;
10
protected $expires;
11
12
private $object = self::ATTACHABLE;
13
14
const TYPE_STANDARD = 'api';
15
const TYPE_COMMANDLINE = 'cli';
16
const TYPE_CLUSTER = 'clr';
17
18
protected function getConfiguration() {
19
return array(
20
self::CONFIG_COLUMN_SCHEMA => array(
21
'tokenType' => 'text32',
22
'token' => 'text32',
23
'expires' => 'epoch?',
24
),
25
self::CONFIG_KEY_SCHEMA => array(
26
'key_object' => array(
27
'columns' => array('objectPHID', 'tokenType'),
28
),
29
'key_token' => array(
30
'columns' => array('token'),
31
'unique' => true,
32
),
33
'key_expires' => array(
34
'columns' => array('expires'),
35
),
36
),
37
) + parent::getConfiguration();
38
}
39
40
public static function loadClusterTokenForUser(PhabricatorUser $user) {
41
if (!$user->isLoggedIn()) {
42
return null;
43
}
44
45
if ($user->hasConduitClusterToken()) {
46
return $user->getConduitClusterToken();
47
}
48
49
$tokens = id(new PhabricatorConduitTokenQuery())
50
->setViewer($user)
51
->withObjectPHIDs(array($user->getPHID()))
52
->withTokenTypes(array(self::TYPE_CLUSTER))
53
->withExpired(false)
54
->execute();
55
56
// Only return a token if it has at least 5 minutes left before
57
// expiration. Cluster tokens cycle regularly, so we don't want to use
58
// one that's going to expire momentarily.
59
$now = PhabricatorTime::getNow();
60
$must_expire_after = $now + phutil_units('5 minutes in seconds');
61
62
$valid_token = null;
63
foreach ($tokens as $token) {
64
if ($token->getExpires() > $must_expire_after) {
65
$valid_token = $token;
66
break;
67
}
68
}
69
70
// We didn't find any existing tokens (or the existing tokens are all about
71
// to expire) so generate a new token.
72
if (!$valid_token) {
73
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
74
$valid_token = self::initializeNewToken(
75
$user->getPHID(),
76
self::TYPE_CLUSTER);
77
$valid_token->save();
78
unset($unguarded);
79
}
80
81
$user->attachConduitClusterToken($valid_token);
82
83
return $valid_token;
84
}
85
86
public static function initializeNewToken($object_phid, $token_type) {
87
$token = new PhabricatorConduitToken();
88
$token->objectPHID = $object_phid;
89
$token->tokenType = $token_type;
90
$token->expires = $token->getTokenExpires($token_type);
91
92
$secret = $token_type.'-'.Filesystem::readRandomCharacters(32);
93
$secret = substr($secret, 0, 32);
94
$token->token = $secret;
95
96
return $token;
97
}
98
99
public static function getTokenTypeName($type) {
100
$map = array(
101
self::TYPE_STANDARD => pht('Standard API Token'),
102
self::TYPE_COMMANDLINE => pht('Command Line API Token'),
103
self::TYPE_CLUSTER => pht('Cluster API Token'),
104
);
105
106
return idx($map, $type, $type);
107
}
108
109
public static function getAllTokenTypes() {
110
return array(
111
self::TYPE_STANDARD,
112
self::TYPE_COMMANDLINE,
113
self::TYPE_CLUSTER,
114
);
115
}
116
117
private function getTokenExpires($token_type) {
118
$now = PhabricatorTime::getNow();
119
switch ($token_type) {
120
case self::TYPE_STANDARD:
121
return null;
122
case self::TYPE_COMMANDLINE:
123
return $now + phutil_units('1 hour in seconds');
124
case self::TYPE_CLUSTER:
125
return $now + phutil_units('30 minutes in seconds');
126
default:
127
throw new Exception(
128
pht('Unknown Conduit token type "%s"!', $token_type));
129
}
130
}
131
132
public function getPublicTokenName() {
133
switch ($this->getTokenType()) {
134
case self::TYPE_CLUSTER:
135
return pht('Cluster API Token');
136
default:
137
return substr($this->getToken(), 0, 8).'...';
138
}
139
}
140
141
public function getObject() {
142
return $this->assertAttached($this->object);
143
}
144
145
public function attachObject(PhabricatorUser $object) {
146
$this->object = $object;
147
return $this;
148
}
149
150
151
/* -( PhabricatorPolicyInterface )----------------------------------------- */
152
153
154
public function getCapabilities() {
155
return array(
156
PhabricatorPolicyCapability::CAN_VIEW,
157
PhabricatorPolicyCapability::CAN_EDIT,
158
);
159
}
160
161
public function getPolicy($capability) {
162
return $this->getObject()->getPolicy($capability);
163
}
164
165
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
166
return $this->getObject()->hasAutomaticCapability($capability, $viewer);
167
}
168
169
public function describeAutomaticCapability($capability) {
170
return pht(
171
'Conduit tokens inherit the policies of the user they authenticate.');
172
}
173
174
}
175
176