Skip to content

Commit 992c199

Browse files
author
epriestley
committedJun 4, 2015
Add "Mailing List" users
Summary: Ref T8387. Adds new mailing list users. This doesn't migrate anything yet. I also need to update the "Email Addresses" panel to let administrators change the list address. Test Plan: - Created and edited a mailing list user. - Viewed profile. - Viewed People list. - Searched for lists / nonlists. - Grepped for all uses of `getIsDisabled()` / `getIsSystemAgent()` and added relevant corresponding behaviors. - Hit the web/api/ssh session blocks. Reviewers: btrahan Reviewed By: btrahan Subscribers: eadler, tycho.tatitscheff, epriestley Maniphest Tasks: T8387 Differential Revision: https://secure.phabricator.com/D13123
1 parent 13f0dac commit 992c199

22 files changed

+244
-43
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE {$NAMESPACE}_user.user
2+
ADD isMailingList BOOL NOT NULL;

‎scripts/ssh/ssh-exec.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@
182182
'P' => $user->getPHID(),
183183
));
184184

185-
if (!$user->isUserActivated()) {
185+
if (!$user->canEstablishSSHSessions()) {
186186
throw new Exception(
187187
pht(
188-
'Your account ("%s") is not activated. Visit the web interface '.
189-
'for more information.',
188+
'Your account ("%s") does not have permission to establish SSH '.
189+
'sessions. Visit the web interface for more information.',
190190
$user->getUsername()));
191191
}
192192

‎scripts/user/account_admin.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125

126126
$is_system_agent = $user->getIsSystemAgent();
127127
$set_system_agent = phutil_console_confirm(
128-
pht('Is this user a bot/script?'),
128+
pht('Is this user a bot?'),
129129
$default_no = !$is_system_agent);
130130

131131
$verify_email = null;
@@ -165,7 +165,7 @@
165165

166166
printf(
167167
$tpl,
168-
pht('Bot/Script'),
168+
pht('Bot'),
169169
$original->getIsSystemAgent() ? 'Y' : 'N',
170170
$set_system_agent ? 'Y' : 'N');
171171

‎src/applications/auth/engine/PhabricatorAuthSessionEngine.php

+15-1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,21 @@ public function loadUserForSession($session_type, $session_token) {
158158
$session_dict[substr($key, 2)] = $value;
159159
}
160160
}
161+
162+
$user = $user_table->loadFromArray($info);
163+
switch ($session_type) {
164+
case PhabricatorAuthSession::TYPE_WEB:
165+
// Explicitly prevent bots and mailing lists from establishing web
166+
// sessions. It's normally impossible to attach authentication to these
167+
// accounts, and likewise impossible to generate sessions, but it's
168+
// technically possible that a session could exist in the database. If
169+
// one does somehow, refuse to load it.
170+
if (!$user->canEstablishWebSessions()) {
171+
return null;
172+
}
173+
break;
174+
}
175+
161176
$session = id(new PhabricatorAuthSession())->loadFromArray($session_dict);
162177

163178
$ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
@@ -181,7 +196,6 @@ public function loadUserForSession($session_type, $session_token) {
181196
unset($unguarded);
182197
}
183198

184-
$user = $user_table->loadFromArray($info);
185199
$user->attachSession($session);
186200
return $user;
187201
}

‎src/applications/conduit/controller/PhabricatorConduitAPIController.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -475,10 +475,10 @@ private function validateAuthenticatedUser(
475475
ConduitAPIRequest $request,
476476
PhabricatorUser $user) {
477477

478-
if (!$user->isUserActivated()) {
478+
if (!$user->canEstablishAPISessions()) {
479479
return array(
480-
'ERR-USER-DISABLED',
481-
pht('User account is not activated.'),
480+
'ERR-INVALID-AUTH',
481+
pht('User account is not permitted to use the API.'),
482482
);
483483
}
484484

‎src/applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ public function getPanelGroup() {
2020
}
2121

2222
public function isEnabled() {
23+
if ($this->getUser()->getIsMailingList()) {
24+
return false;
25+
}
26+
2327
return true;
2428
}
2529

‎src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public function getPanelGroup() {
1919
}
2020

2121
public function isEnabled() {
22+
if ($this->getUser()->getIsMailingList()) {
23+
return false;
24+
}
25+
2226
return PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth');
2327
}
2428

‎src/applications/people/conduit/UserConduitAPIMethod.php

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ protected function buildUserInformationDictionary(
1818
if ($user->getIsSystemAgent()) {
1919
$roles[] = 'agent';
2020
}
21+
if ($user->getIsMailingList()) {
22+
$roles[] = 'list';
23+
}
2124
if ($user->getIsAdmin()) {
2225
$roles[] = 'admin';
2326
}

‎src/applications/people/controller/PhabricatorPeopleCreateController.php

+37-16
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ final class PhabricatorPeopleCreateController
44
extends PhabricatorPeopleController {
55

66
public function handleRequest(AphrontRequest $request) {
7-
$this->requireApplicationCapability(
8-
PeopleCreateUsersCapability::CAPABILITY);
97
$admin = $request->getUser();
108

119
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
@@ -17,7 +15,7 @@ public function handleRequest(AphrontRequest $request) {
1715
if ($request->isFormPost()) {
1816
$v_type = $request->getStr('type');
1917

20-
if ($v_type == 'standard' || $v_type == 'bot') {
18+
if ($v_type == 'standard' || $v_type == 'bot' || $v_type == 'list') {
2119
return id(new AphrontRedirectResponse())->setURI(
2220
$this->getApplicationURI('new/'.$v_type.'/'));
2321
}
@@ -41,6 +39,41 @@ public function handleRequest(AphrontRequest $request) {
4139
$bot_admin = pht(
4240
'Administrators have greater access to edit these accounts.');
4341

42+
$types = array();
43+
44+
$can_create = $this->hasApplicationCapability(
45+
PeopleCreateUsersCapability::CAPABILITY);
46+
if ($can_create) {
47+
$types[] = array(
48+
'type' => 'standard',
49+
'name' => pht('Create Standard User'),
50+
'help' => pht('Create a standard user account.'),
51+
);
52+
}
53+
54+
$types[] = array(
55+
'type' => 'bot',
56+
'name' => pht('Create Bot User'),
57+
'help' => pht('Create a new user for use with automated scripts.'),
58+
);
59+
60+
$types[] = array(
61+
'type' => 'list',
62+
'name' => pht('Create Mailing List User'),
63+
'help' => pht(
64+
'Create a mailing list user to represent an existing, external '.
65+
'mailing list like a Google Group or a Mailman list.'),
66+
);
67+
68+
$buttons = id(new AphrontFormRadioButtonControl())
69+
->setLabel(pht('Account Type'))
70+
->setName('type')
71+
->setValue($v_type);
72+
73+
foreach ($types as $type) {
74+
$buttons->addButton($type['type'], $type['name'], $type['help']);
75+
}
76+
4477
$form = id(new AphrontFormView())
4578
->setUser($admin)
4679
->appendRemarkupInstructions(
@@ -49,19 +82,7 @@ public function handleRequest(AphrontRequest $request) {
4982
'explanation of user account types, see [[ %s | User Guide: '.
5083
'Account Roles ]].',
5184
PhabricatorEnv::getDoclink('User Guide: Account Roles')))
52-
->appendChild(
53-
id(new AphrontFormRadioButtonControl())
54-
->setLabel(pht('Account Type'))
55-
->setName('type')
56-
->setValue($v_type)
57-
->addButton(
58-
'standard',
59-
pht('Create Standard User'),
60-
hsprintf('%s<br /><br />%s', $standard_caption, $standard_admin))
61-
->addButton(
62-
'bot',
63-
pht('Create Bot/Script User'),
64-
hsprintf('%s<br /><br />%s', $bot_caption, $bot_admin)))
85+
->appendChild($buttons)
6586
->appendChild(
6687
id(new AphrontFormSubmitControl())
6788
->addCancelButton($this->getApplicationURI())

‎src/applications/people/controller/PhabricatorPeopleListController.php

+1-9
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,12 @@ protected function buildApplicationCrumbs() {
3333
$crumbs = parent::buildApplicationCrumbs();
3434
$viewer = $this->getRequest()->getUser();
3535

36-
$can_create = $this->hasApplicationCapability(
37-
PeopleCreateUsersCapability::CAPABILITY);
38-
if ($can_create) {
36+
if ($viewer->getIsAdmin()) {
3937
$crumbs->addAction(
4038
id(new PHUIListItemView())
4139
->setName(pht('Create New User'))
4240
->setHref($this->getApplicationURI('create/'))
4341
->setIcon('fa-plus-square'));
44-
} else if ($viewer->getIsAdmin()) {
45-
$crumbs->addAction(
46-
id(new PHUIListItemView())
47-
->setName(pht('Create New Bot'))
48-
->setHref($this->getApplicationURI('new/bot/'))
49-
->setIcon('fa-plus-square'));
5042
}
5143

5244
return $crumbs;

‎src/applications/people/controller/PhabricatorPeopleNewController.php

+20-7
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ public function handleRequest(AphrontRequest $request) {
77
$type = $request->getURIData('type');
88
$admin = $request->getUser();
99

10+
$is_bot = false;
11+
$is_list = false;
1012
switch ($type) {
1113
case 'standard':
1214
$this->requireApplicationCapability(
1315
PeopleCreateUsersCapability::CAPABILITY);
14-
$is_bot = false;
1516
break;
1617
case 'bot':
1718
$is_bot = true;
1819
break;
20+
case 'list':
21+
$is_list = true;
22+
break;
1923
default:
2024
return new Aphront404Response();
2125
}
@@ -77,8 +81,8 @@ public function handleRequest(AphrontRequest $request) {
7781
// Automatically approve the user, since an admin is creating them.
7882
$user->setIsApproved(1);
7983

80-
// If the user is a bot, approve their email too.
81-
if ($is_bot) {
84+
// If the user is a bot or list, approve their email too.
85+
if ($is_bot || $is_list) {
8286
$email->setIsVerified(1);
8387
}
8488

@@ -92,7 +96,13 @@ public function handleRequest(AphrontRequest $request) {
9296
->makeSystemAgentUser($user, true);
9397
}
9498

95-
if ($welcome_checked && !$is_bot) {
99+
if ($is_list) {
100+
id(new PhabricatorUserEditor())
101+
->setActor($admin)
102+
->makeMailingListUser($user, true);
103+
}
104+
105+
if ($welcome_checked && !$is_bot && !$is_list) {
96106
$user->sendWelcomeEmail($admin);
97107
}
98108

@@ -123,7 +133,10 @@ public function handleRequest(AphrontRequest $request) {
123133

124134
if ($is_bot) {
125135
$form->appendRemarkupInstructions(
126-
pht('You are creating a new **bot/script** user account.'));
136+
pht('You are creating a new **bot** user account.'));
137+
} else if ($is_list) {
138+
$form->appendRemarkupInstructions(
139+
pht('You are creating a new **mailing list** user account.'));
127140
} else {
128141
$form->appendRemarkupInstructions(
129142
pht('You are creating a new **standard** user account.'));
@@ -150,7 +163,7 @@ public function handleRequest(AphrontRequest $request) {
150163
->setCaption(PhabricatorUserEmail::describeAllowedAddresses())
151164
->setError($e_email));
152165

153-
if (!$is_bot) {
166+
if (!$is_bot && !$is_list) {
154167
$form->appendChild(
155168
id(new AphrontFormCheckboxControl())
156169
->addCheckbox(
@@ -171,7 +184,7 @@ public function handleRequest(AphrontRequest $request) {
171184
->appendChild(id(new AphrontFormDividerControl()))
172185
->appendRemarkupInstructions(
173186
pht(
174-
'**Why do bot/script accounts need an email address?**'.
187+
'**Why do bot accounts need an email address?**'.
175188
"\n\n".
176189
'Although bots do not normally receive email from Phabricator, '.
177190
'they can interact with other systems which require an email '.

‎src/applications/people/customfield/PhabricatorUserRolesField.php

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public function renderPropertyViewValue(array $handles) {
3737
if ($user->getIsSystemAgent()) {
3838
$roles[] = pht('Bot');
3939
}
40+
if ($user->getIsMailingList()) {
41+
$roles[] = pht('Mailing List');
42+
}
4043

4144
if ($roles) {
4245
return implode(', ', $roles);

‎src/applications/people/editor/PhabricatorUserEditor.php

+37
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,43 @@ public function makeSystemAgentUser(PhabricatorUser $user, $system_agent) {
278278
return $this;
279279
}
280280

281+
/**
282+
* @task role
283+
*/
284+
public function makeMailingListUser(PhabricatorUser $user, $mailing_list) {
285+
$actor = $this->requireActor();
286+
287+
if (!$user->getID()) {
288+
throw new Exception(pht('User has not been created yet!'));
289+
}
290+
291+
$user->openTransaction();
292+
$user->beginWriteLocking();
293+
294+
$user->reload();
295+
if ($user->getIsMailingList() == $mailing_list) {
296+
$user->endWriteLocking();
297+
$user->killTransaction();
298+
return $this;
299+
}
300+
301+
$log = PhabricatorUserLog::initializeNewLog(
302+
$actor,
303+
$user->getPHID(),
304+
PhabricatorUserLog::ACTION_MAILING_LIST);
305+
$log->setOldValue($user->getIsMailingList());
306+
$log->setNewValue($mailing_list);
307+
308+
$user->setIsMailingList((int)$mailing_list);
309+
$user->save();
310+
311+
$log->save();
312+
313+
$user->endWriteLocking();
314+
$user->saveTransaction();
315+
316+
return $this;
317+
}
281318

282319
/**
283320
* @task role

‎src/applications/people/phid/PhabricatorPeopleUserPHIDType.php

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ public function loadHandles(
4444
$handle->setFullName($user->getFullName());
4545
$handle->setImageURI($user->getProfileImageURI());
4646

47+
if ($user->getIsMailingList()) {
48+
$handle->setIcon('fa-envelope-o');
49+
}
50+
4751
$availability = null;
4852
if (!$user->isUserActivated()) {
4953
$availability = PhabricatorObjectHandle::AVAILABILITY_DISABLED;

‎src/applications/people/query/PhabricatorPeopleQuery.php

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ final class PhabricatorPeopleQuery
1212
private $dateCreatedBefore;
1313
private $isAdmin;
1414
private $isSystemAgent;
15+
private $isMailingList;
1516
private $isDisabled;
1617
private $isApproved;
1718
private $nameLike;
@@ -67,6 +68,11 @@ public function withIsSystemAgent($system_agent) {
6768
return $this;
6869
}
6970

71+
public function withIsMailingList($mailing_list) {
72+
$this->isMailingList = $mailing_list;
73+
return $this;
74+
}
75+
7076
public function withIsDisabled($disabled) {
7177
$this->isDisabled = $disabled;
7278
return $this;
@@ -340,6 +346,13 @@ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
340346
(int)$this->isSystemAgent);
341347
}
342348

349+
if ($this->isMailingList !== null) {
350+
$where[] = qsprintf(
351+
$conn_r,
352+
'user.isMailingList = %d',
353+
(int)$this->isMailingList);
354+
}
355+
343356
if (strlen($this->nameLike)) {
344357
$where[] = qsprintf(
345358
$conn_r,

0 commit comments

Comments
 (0)
Failed to load comments.