@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 PhabricatorPeopleNewController
4 extends PhabricatorPeopleController {
5
6 public function handleRequest(AphrontRequest $request) {
7 $type = $request->getURIData('type');
8 $admin = $request->getUser();
9
10 id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
11 $admin,
12 $request,
13 $this->getApplicationURI());
14
15 $is_bot = false;
16 $is_list = false;
17 switch ($type) {
18 case 'standard':
19 $this->requireApplicationCapability(
20 PeopleCreateUsersCapability::CAPABILITY);
21 break;
22 case 'bot':
23 $is_bot = true;
24 break;
25 case 'list':
26 $is_list = true;
27 break;
28 default:
29 return new Aphront404Response();
30 }
31
32 $user = new PhabricatorUser();
33 $require_real_name = PhabricatorEnv::getEnvConfig('user.require-real-name');
34
35 $e_username = true;
36 $e_realname = $require_real_name ? true : null;
37 $e_email = true;
38 $errors = array();
39
40 $welcome_checked = true;
41
42 $new_email = null;
43
44 if ($request->isFormPost()) {
45 $welcome_checked = $request->getInt('welcome');
46
47 $user->setUsername($request->getStr('username'));
48
49 $new_email = $request->getStr('email');
50 if (!strlen($new_email)) {
51 $errors[] = pht('Email is required.');
52 $e_email = pht('Required');
53 } else if (!PhabricatorUserEmail::isValidAddress($new_email)) {
54 $errors[] = PhabricatorUserEmail::describeValidAddresses();
55 $e_email = pht('Invalid');
56 } else if (!PhabricatorUserEmail::isAllowedAddress($new_email)) {
57 $errors[] = PhabricatorUserEmail::describeAllowedAddresses();
58 $e_email = pht('Not Allowed');
59 } else {
60 $e_email = null;
61 }
62
63 $user->setRealName($request->getStr('realname'));
64
65 $username = $user->getUsername();
66
67 if (!strlen($username)) {
68 $errors[] = pht('Username is required.');
69 $e_username = pht('Required');
70 } else if (!PhabricatorUser::validateUsername($username)) {
71 $errors[] = PhabricatorUser::describeValidUsername($username);
72 $e_username = pht('Invalid');
73 } else {
74 $e_username = null;
75 }
76
77 if (!strlen($user->getRealName()) && $require_real_name) {
78 $errors[] = pht('Real name is required.');
79 $e_realname = pht('Required');
80 } else {
81 $e_realname = null;
82 }
83
84 if (!$errors) {
85 try {
86
87 $email = id(new PhabricatorUserEmail())
88 ->setAddress($new_email)
89 ->setIsVerified(0);
90
91 // Automatically approve the user, since an admin is creating them.
92 $user->setIsApproved(1);
93
94 // If the user is a bot or list, approve their email too.
95 if ($is_bot || $is_list) {
96 $email->setIsVerified(1);
97 }
98
99 id(new PhabricatorUserEditor())
100 ->setActor($admin)
101 ->createNewUser($user, $email);
102
103 if ($is_bot) {
104 id(new PhabricatorUserEditor())
105 ->setActor($admin)
106 ->makeSystemAgentUser($user, true);
107 }
108
109 if ($is_list) {
110 id(new PhabricatorUserEditor())
111 ->setActor($admin)
112 ->makeMailingListUser($user, true);
113 }
114
115 if ($welcome_checked) {
116 $welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
117 ->setSender($admin)
118 ->setRecipient($user);
119 if ($welcome_engine->canSendMail()) {
120 $welcome_engine->sendMail();
121 }
122 }
123
124 $response = id(new AphrontRedirectResponse())
125 ->setURI('/p/'.$user->getUsername().'/');
126 return $response;
127 } catch (AphrontDuplicateKeyQueryException $ex) {
128 $errors[] = pht('Username and email must be unique.');
129
130 $same_username = id(new PhabricatorUser())
131 ->loadOneWhere('username = %s', $user->getUsername());
132 $same_email = id(new PhabricatorUserEmail())
133 ->loadOneWhere('address = %s', $new_email);
134
135 if ($same_username) {
136 $e_username = pht('Duplicate');
137 }
138
139 if ($same_email) {
140 $e_email = pht('Duplicate');
141 }
142 }
143 }
144 }
145
146 $form = id(new AphrontFormView())
147 ->setUser($admin);
148
149 if ($is_bot) {
150 $title = pht('Create New Bot');
151 $form->appendRemarkupInstructions(
152 pht('You are creating a new **bot** user account.'));
153 } else if ($is_list) {
154 $title = pht('Create New Mailing List');
155 $form->appendRemarkupInstructions(
156 pht('You are creating a new **mailing list** user account.'));
157 } else {
158 $title = pht('Create New User');
159 $form->appendRemarkupInstructions(
160 pht('You are creating a new **standard** user account.'));
161 }
162
163 $form
164 ->appendChild(
165 id(new AphrontFormTextControl())
166 ->setLabel(pht('Username'))
167 ->setName('username')
168 ->setValue($user->getUsername())
169 ->setError($e_username))
170 ->appendChild(
171 id(new AphrontFormTextControl())
172 ->setLabel(pht('Real Name'))
173 ->setName('realname')
174 ->setValue($user->getRealName())
175 ->setError($e_realname))
176 ->appendChild(
177 id(new AphrontFormTextControl())
178 ->setLabel(pht('Email'))
179 ->setName('email')
180 ->setValue($new_email)
181 ->setCaption(PhabricatorUserEmail::describeAllowedAddresses())
182 ->setError($e_email));
183
184 if (!$is_bot && !$is_list) {
185 $form->appendChild(
186 id(new AphrontFormCheckboxControl())
187 ->addCheckbox(
188 'welcome',
189 1,
190 pht(
191 'Send "Welcome to %s" email with login instructions.',
192 PlatformSymbols::getPlatformServerName()),
193 $welcome_checked));
194 }
195
196 $form
197 ->appendChild(
198 id(new AphrontFormSubmitControl())
199 ->addCancelButton($this->getApplicationURI())
200 ->setValue(pht('Create User')));
201
202 if ($is_bot) {
203 $form
204 ->appendChild(id(new AphrontFormDividerControl()))
205 ->appendRemarkupInstructions(
206 pht(
207 '**Why do bot accounts need an email address?**'.
208 "\n\n".
209 'Although bots do not normally receive email, they can interact '.
210 'with other systems which require an email address. Examples '.
211 'include:'.
212 "\n\n".
213 " - If the account takes actions which //send// email, we need ".
214 " an address to use in the //From// header.\n".
215 " - If the account creates commits, Git and Mercurial require ".
216 " an email address for authorship.\n".
217 " - If you send email //to// this server on behalf of the ".
218 " account, the address can identify the sender.\n".
219 " - Some internal authentication functions depend on accounts ".
220 " having an email address.\n".
221 "\n\n".
222 "The address will automatically be verified, so you do not need ".
223 "to be able to receive mail at this address, and can enter some ".
224 "invalid or nonexistent (but correctly formatted) address like ".
225 "`bot@yourcompany.com` if you prefer."));
226 }
227
228 $box = id(new PHUIObjectBoxView())
229 ->setHeaderText($title)
230 ->setFormErrors($errors)
231 ->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
232 ->setForm($form);
233
234 $crumbs = $this->buildApplicationCrumbs();
235 $crumbs->addTextCrumb($title);
236 $crumbs->setBorder(true);
237
238 $view = id(new PHUITwoColumnView())
239 ->setFooter($box);
240
241 return $this->newPage()
242 ->setTitle($title)
243 ->setCrumbs($crumbs)
244 ->appendChild($view);
245 }
246
247}