Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/auth/data/PhabricatorAuthInviteAction.php
12256 views
1
<?php
2
3
final class PhabricatorAuthInviteAction extends Phobject {
4
5
private $rawInput;
6
private $emailAddress;
7
private $userPHID;
8
private $issues = array();
9
private $action;
10
11
const ACTION_SEND = 'invite.send';
12
const ACTION_ERROR = 'invite.error';
13
const ACTION_IGNORE = 'invite.ignore';
14
15
const ISSUE_PARSE = 'invite.parse';
16
const ISSUE_DUPLICATE = 'invite.duplicate';
17
const ISSUE_UNVERIFIED = 'invite.unverified';
18
const ISSUE_VERIFIED = 'invite.verified';
19
const ISSUE_INVITED = 'invite.invited';
20
const ISSUE_ACCEPTED = 'invite.accepted';
21
22
public function getRawInput() {
23
return $this->rawInput;
24
}
25
26
public function getEmailAddress() {
27
return $this->emailAddress;
28
}
29
30
public function getUserPHID() {
31
return $this->userPHID;
32
}
33
34
public function getIssues() {
35
return $this->issues;
36
}
37
38
public function setAction($action) {
39
$this->action = $action;
40
return $this;
41
}
42
43
public function getAction() {
44
return $this->action;
45
}
46
47
public function willSend() {
48
return ($this->action == self::ACTION_SEND);
49
}
50
51
public function getShortNameForIssue($issue) {
52
$map = array(
53
self::ISSUE_PARSE => pht('Not a Valid Email Address'),
54
self::ISSUE_DUPLICATE => pht('Address Duplicated in Input'),
55
self::ISSUE_UNVERIFIED => pht('Unverified User Email'),
56
self::ISSUE_VERIFIED => pht('Verified User Email'),
57
self::ISSUE_INVITED => pht('Previously Invited'),
58
self::ISSUE_ACCEPTED => pht('Already Accepted Invite'),
59
);
60
61
return idx($map, $issue);
62
}
63
64
public function getShortNameForAction($action) {
65
$map = array(
66
self::ACTION_SEND => pht('Will Send Invite'),
67
self::ACTION_ERROR => pht('Address Error'),
68
self::ACTION_IGNORE => pht('Will Ignore Address'),
69
);
70
71
return idx($map, $action);
72
}
73
74
public function getIconForAction($action) {
75
switch ($action) {
76
case self::ACTION_SEND:
77
$icon = 'fa-envelope-o';
78
$color = 'green';
79
break;
80
case self::ACTION_IGNORE:
81
$icon = 'fa-ban';
82
$color = 'grey';
83
break;
84
case self::ACTION_ERROR:
85
$icon = 'fa-exclamation-triangle';
86
$color = 'red';
87
break;
88
}
89
90
return id(new PHUIIconView())
91
->setIcon("{$icon} {$color}");
92
}
93
94
public static function newActionListFromAddresses(
95
PhabricatorUser $viewer,
96
array $addresses) {
97
98
$results = array();
99
foreach ($addresses as $address) {
100
$result = new PhabricatorAuthInviteAction();
101
$result->rawInput = $address;
102
103
$email = new PhutilEmailAddress($address);
104
$result->emailAddress = phutil_utf8_strtolower($email->getAddress());
105
106
if (!preg_match('/^\S+@\S+\.\S+\z/', $result->emailAddress)) {
107
$result->issues[] = self::ISSUE_PARSE;
108
}
109
110
$results[] = $result;
111
}
112
113
// Identify duplicates.
114
$address_groups = mgroup($results, 'getEmailAddress');
115
foreach ($address_groups as $address => $group) {
116
if (count($group) > 1) {
117
foreach ($group as $action) {
118
$action->issues[] = self::ISSUE_DUPLICATE;
119
}
120
}
121
}
122
123
// Identify addresses which are already in the system.
124
$addresses = mpull($results, 'getEmailAddress');
125
$email_objects = id(new PhabricatorUserEmail())->loadAllWhere(
126
'address IN (%Ls)',
127
$addresses);
128
129
$email_map = array();
130
foreach ($email_objects as $email_object) {
131
$address_key = phutil_utf8_strtolower($email_object->getAddress());
132
$email_map[$address_key] = $email_object;
133
}
134
135
// Identify outstanding invites.
136
$invites = id(new PhabricatorAuthInviteQuery())
137
->setViewer($viewer)
138
->withEmailAddresses($addresses)
139
->execute();
140
$invite_map = mpull($invites, null, 'getEmailAddress');
141
142
foreach ($results as $action) {
143
$email = idx($email_map, $action->getEmailAddress());
144
if ($email) {
145
if ($email->getUserPHID()) {
146
$action->userPHID = $email->getUserPHID();
147
if ($email->getIsVerified()) {
148
$action->issues[] = self::ISSUE_VERIFIED;
149
} else {
150
$action->issues[] = self::ISSUE_UNVERIFIED;
151
}
152
}
153
}
154
155
$invite = idx($invite_map, $action->getEmailAddress());
156
if ($invite) {
157
if ($invite->getAcceptedByPHID()) {
158
$action->issues[] = self::ISSUE_ACCEPTED;
159
if (!$action->userPHID) {
160
// This could be different from the user who is currently attached
161
// to the email address if the address was removed or added to a
162
// different account later. Only show it if the address was
163
// removed, since the current status is more up-to-date otherwise.
164
$action->userPHID = $invite->getAcceptedByPHID();
165
}
166
} else {
167
$action->issues[] = self::ISSUE_INVITED;
168
}
169
}
170
}
171
172
foreach ($results as $result) {
173
foreach ($result->getIssues() as $issue) {
174
switch ($issue) {
175
case self::ISSUE_PARSE:
176
$result->action = self::ACTION_ERROR;
177
break;
178
case self::ISSUE_ACCEPTED:
179
case self::ISSUE_VERIFIED:
180
$result->action = self::ACTION_IGNORE;
181
break;
182
}
183
}
184
if (!$result->action) {
185
$result->action = self::ACTION_SEND;
186
}
187
}
188
189
return $results;
190
}
191
192
public function sendInvite(PhabricatorUser $actor, $template) {
193
if (!$this->willSend()) {
194
throw new Exception(pht('Invite action is not a send action!'));
195
}
196
197
if (!preg_match('/{\$INVITE_URI}/', $template)) {
198
throw new Exception(pht('Invite template does not include invite URI!'));
199
}
200
201
PhabricatorWorker::scheduleTask(
202
'PhabricatorAuthInviteWorker',
203
array(
204
'address' => $this->getEmailAddress(),
205
'template' => $template,
206
'authorPHID' => $actor->getPHID(),
207
));
208
}
209
210
}
211
212