Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/people/storage/PhabricatorExternalAccount.php
12256 views
1
<?php
2
3
final class PhabricatorExternalAccount
4
extends PhabricatorUserDAO
5
implements
6
PhabricatorPolicyInterface,
7
PhabricatorDestructibleInterface {
8
9
protected $userPHID;
10
protected $accountSecret;
11
protected $displayName;
12
protected $username;
13
protected $realName;
14
protected $email;
15
protected $emailVerified = 0;
16
protected $accountURI;
17
protected $profileImagePHID;
18
protected $properties = array();
19
protected $providerConfigPHID;
20
21
// TODO: Remove these (see T13493). These columns are obsolete and have
22
// no readers and only trivial writers.
23
protected $accountType;
24
protected $accountDomain;
25
protected $accountID;
26
27
private $profileImageFile = self::ATTACHABLE;
28
private $providerConfig = self::ATTACHABLE;
29
private $accountIdentifiers = self::ATTACHABLE;
30
31
public function getProfileImageFile() {
32
return $this->assertAttached($this->profileImageFile);
33
}
34
35
public function attachProfileImageFile(PhabricatorFile $file) {
36
$this->profileImageFile = $file;
37
return $this;
38
}
39
40
public function generatePHID() {
41
return PhabricatorPHID::generateNewPHID(
42
PhabricatorPeopleExternalPHIDType::TYPECONST);
43
}
44
45
protected function getConfiguration() {
46
return array(
47
self::CONFIG_AUX_PHID => true,
48
self::CONFIG_SERIALIZATION => array(
49
'properties' => self::SERIALIZATION_JSON,
50
),
51
self::CONFIG_COLUMN_SCHEMA => array(
52
'userPHID' => 'phid?',
53
'accountType' => 'text16',
54
'accountDomain' => 'text64',
55
'accountSecret' => 'text?',
56
'accountID' => 'text64',
57
'displayName' => 'text255?',
58
'username' => 'text255?',
59
'realName' => 'text255?',
60
'email' => 'text255?',
61
'emailVerified' => 'bool',
62
'profileImagePHID' => 'phid?',
63
'accountURI' => 'text255?',
64
),
65
self::CONFIG_KEY_SCHEMA => array(
66
'key_user' => array(
67
'columns' => array('userPHID'),
68
),
69
'key_provider' => array(
70
'columns' => array('providerConfigPHID', 'userPHID'),
71
),
72
),
73
) + parent::getConfiguration();
74
}
75
76
public function save() {
77
if (!$this->getAccountSecret()) {
78
$this->setAccountSecret(Filesystem::readRandomCharacters(32));
79
}
80
81
$this->openTransaction();
82
83
$result = parent::save();
84
85
$account_phid = $this->getPHID();
86
$config_phid = $this->getProviderConfigPHID();
87
88
if ($this->accountIdentifiers !== self::ATTACHABLE) {
89
foreach ($this->getAccountIdentifiers() as $identifier) {
90
$identifier
91
->setExternalAccountPHID($account_phid)
92
->setProviderConfigPHID($config_phid)
93
->save();
94
}
95
}
96
97
$this->saveTransaction();
98
99
return $result;
100
}
101
102
public function unlinkAccount() {
103
104
// When unlinking an account, we disassociate it from the user and
105
// remove all the identifying information. We retain the PHID, the
106
// object itself, and the "ExternalAccountIdentifier" objects in the
107
// external table.
108
109
// TODO: This unlinks (but does not destroy) any profile image.
110
111
return $this
112
->setUserPHID(null)
113
->setDisplayName(null)
114
->setUsername(null)
115
->setRealName(null)
116
->setEmail(null)
117
->setEmailVerified(0)
118
->setProfileImagePHID(null)
119
->setAccountURI(null)
120
->setProperties(array())
121
->save();
122
}
123
124
public function setProperty($key, $value) {
125
$this->properties[$key] = $value;
126
return $this;
127
}
128
129
public function getProperty($key, $default = null) {
130
return idx($this->properties, $key, $default);
131
}
132
133
public function isUsableForLogin() {
134
$config = $this->getProviderConfig();
135
if (!$config->getIsEnabled()) {
136
return false;
137
}
138
139
$provider = $config->getProvider();
140
if (!$provider->shouldAllowLogin()) {
141
return false;
142
}
143
144
return true;
145
}
146
147
public function attachProviderConfig(PhabricatorAuthProviderConfig $config) {
148
$this->providerConfig = $config;
149
return $this;
150
}
151
152
public function getProviderConfig() {
153
return $this->assertAttached($this->providerConfig);
154
}
155
156
public function getAccountIdentifiers() {
157
$raw = $this->assertAttached($this->accountIdentifiers);
158
return array_values($raw);
159
}
160
161
public function attachAccountIdentifiers(array $identifiers) {
162
assert_instances_of($identifiers, 'PhabricatorExternalAccountIdentifier');
163
$this->accountIdentifiers = mpull($identifiers, null, 'getIdentifierRaw');
164
return $this;
165
}
166
167
public function appendIdentifier(
168
PhabricatorExternalAccountIdentifier $identifier) {
169
170
$this->assertAttached($this->accountIdentifiers);
171
172
$map = $this->accountIdentifiers;
173
$raw = $identifier->getIdentifierRaw();
174
175
$old = idx($map, $raw);
176
$new = $identifier;
177
178
if ($old === null) {
179
$result = $new;
180
} else {
181
// Here, we already know about an identifier and have rediscovered it.
182
183
// We could copy properties from the new version of the identifier here,
184
// or merge them in some other way (for example, update a "last seen
185
// from the provider" timestamp), but no such properties currently exist.
186
$result = $old;
187
}
188
189
$this->accountIdentifiers[$raw] = $result;
190
191
return $this;
192
}
193
194
195
/* -( PhabricatorPolicyInterface )----------------------------------------- */
196
197
198
public function getCapabilities() {
199
return array(
200
PhabricatorPolicyCapability::CAN_VIEW,
201
PhabricatorPolicyCapability::CAN_EDIT,
202
);
203
}
204
205
public function getPolicy($capability) {
206
switch ($capability) {
207
case PhabricatorPolicyCapability::CAN_VIEW:
208
return PhabricatorPolicies::getMostOpenPolicy();
209
case PhabricatorPolicyCapability::CAN_EDIT:
210
return PhabricatorPolicies::POLICY_NOONE;
211
}
212
}
213
214
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
215
return ($viewer->getPHID() == $this->getUserPHID());
216
}
217
218
public function describeAutomaticCapability($capability) {
219
switch ($capability) {
220
case PhabricatorPolicyCapability::CAN_VIEW:
221
return null;
222
case PhabricatorPolicyCapability::CAN_EDIT:
223
return pht(
224
'External accounts can only be edited by the account owner.');
225
}
226
}
227
228
229
/* -( PhabricatorDestructibleInterface )----------------------------------- */
230
231
232
public function destroyObjectPermanently(
233
PhabricatorDestructionEngine $engine) {
234
235
$viewer = $engine->getViewer();
236
237
$identifiers = id(new PhabricatorExternalAccountIdentifierQuery())
238
->setViewer($viewer)
239
->withExternalAccountPHIDs(array($this->getPHID()))
240
->newIterator();
241
foreach ($identifiers as $identifier) {
242
$engine->destroyObject($identifier);
243
}
244
245
// TODO: This may leave a profile image behind.
246
247
$this->delete();
248
}
249
250
}
251
252