Page MenuHomePhabricator

D13123.diff
No OneTemporary

D13123.diff

diff --git a/resources/sql/autopatches/20150602.mlist.1.sql b/resources/sql/autopatches/20150602.mlist.1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150602.mlist.1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_user.user
+ ADD isMailingList BOOL NOT NULL;
diff --git a/scripts/ssh/ssh-exec.php b/scripts/ssh/ssh-exec.php
--- a/scripts/ssh/ssh-exec.php
+++ b/scripts/ssh/ssh-exec.php
@@ -182,11 +182,11 @@
'P' => $user->getPHID(),
));
- if (!$user->isUserActivated()) {
+ if (!$user->canEstablishSSHSessions()) {
throw new Exception(
pht(
- 'Your account ("%s") is not activated. Visit the web interface '.
- 'for more information.',
+ 'Your account ("%s") does not have permission to establish SSH '.
+ 'sessions. Visit the web interface for more information.',
$user->getUsername()));
}
diff --git a/scripts/user/account_admin.php b/scripts/user/account_admin.php
--- a/scripts/user/account_admin.php
+++ b/scripts/user/account_admin.php
@@ -125,7 +125,7 @@
$is_system_agent = $user->getIsSystemAgent();
$set_system_agent = phutil_console_confirm(
- pht('Is this user a bot/script?'),
+ pht('Is this user a bot?'),
$default_no = !$is_system_agent);
$verify_email = null;
@@ -165,7 +165,7 @@
printf(
$tpl,
- pht('Bot/Script'),
+ pht('Bot'),
$original->getIsSystemAgent() ? 'Y' : 'N',
$set_system_agent ? 'Y' : 'N');
diff --git a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php
--- a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php
+++ b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php
@@ -158,6 +158,21 @@
$session_dict[substr($key, 2)] = $value;
}
}
+
+ $user = $user_table->loadFromArray($info);
+ switch ($session_type) {
+ case PhabricatorAuthSession::TYPE_WEB:
+ // Explicitly prevent bots and mailing lists from establishing web
+ // sessions. It's normally impossible to attach authentication to these
+ // accounts, and likewise impossible to generate sessions, but it's
+ // technically possible that a session could exist in the database. If
+ // one does somehow, refuse to load it.
+ if (!$user->canEstablishWebSessions()) {
+ return null;
+ }
+ break;
+ }
+
$session = id(new PhabricatorAuthSession())->loadFromArray($session_dict);
$ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
@@ -181,7 +196,6 @@
unset($unguarded);
}
- $user = $user_table->loadFromArray($info);
$user->attachSession($session);
return $user;
}
diff --git a/src/applications/conduit/controller/PhabricatorConduitAPIController.php b/src/applications/conduit/controller/PhabricatorConduitAPIController.php
--- a/src/applications/conduit/controller/PhabricatorConduitAPIController.php
+++ b/src/applications/conduit/controller/PhabricatorConduitAPIController.php
@@ -475,10 +475,10 @@
ConduitAPIRequest $request,
PhabricatorUser $user) {
- if (!$user->isUserActivated()) {
+ if (!$user->canEstablishAPISessions()) {
return array(
- 'ERR-USER-DISABLED',
- pht('User account is not activated.'),
+ 'ERR-INVALID-AUTH',
+ pht('User account is not permitted to use the API.'),
);
}
diff --git a/src/applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php b/src/applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php
--- a/src/applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php
+++ b/src/applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php
@@ -20,6 +20,10 @@
}
public function isEnabled() {
+ if ($this->getUser()->getIsMailingList()) {
+ return false;
+ }
+
return true;
}
diff --git a/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php b/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php
--- a/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php
+++ b/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php
@@ -19,6 +19,10 @@
}
public function isEnabled() {
+ if ($this->getUser()->getIsMailingList()) {
+ return false;
+ }
+
return PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth');
}
diff --git a/src/applications/people/conduit/UserConduitAPIMethod.php b/src/applications/people/conduit/UserConduitAPIMethod.php
--- a/src/applications/people/conduit/UserConduitAPIMethod.php
+++ b/src/applications/people/conduit/UserConduitAPIMethod.php
@@ -18,6 +18,9 @@
if ($user->getIsSystemAgent()) {
$roles[] = 'agent';
}
+ if ($user->getIsMailingList()) {
+ $roles[] = 'list';
+ }
if ($user->getIsAdmin()) {
$roles[] = 'admin';
}
diff --git a/src/applications/people/controller/PhabricatorPeopleCreateController.php b/src/applications/people/controller/PhabricatorPeopleCreateController.php
--- a/src/applications/people/controller/PhabricatorPeopleCreateController.php
+++ b/src/applications/people/controller/PhabricatorPeopleCreateController.php
@@ -4,8 +4,6 @@
extends PhabricatorPeopleController {
public function handleRequest(AphrontRequest $request) {
- $this->requireApplicationCapability(
- PeopleCreateUsersCapability::CAPABILITY);
$admin = $request->getUser();
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
@@ -17,7 +15,7 @@
if ($request->isFormPost()) {
$v_type = $request->getStr('type');
- if ($v_type == 'standard' || $v_type == 'bot') {
+ if ($v_type == 'standard' || $v_type == 'bot' || $v_type == 'list') {
return id(new AphrontRedirectResponse())->setURI(
$this->getApplicationURI('new/'.$v_type.'/'));
}
@@ -41,6 +39,41 @@
$bot_admin = pht(
'Administrators have greater access to edit these accounts.');
+ $types = array();
+
+ $can_create = $this->hasApplicationCapability(
+ PeopleCreateUsersCapability::CAPABILITY);
+ if ($can_create) {
+ $types[] = array(
+ 'type' => 'standard',
+ 'name' => pht('Create Standard User'),
+ 'help' => pht('Create a standard user account.'),
+ );
+ }
+
+ $types[] = array(
+ 'type' => 'bot',
+ 'name' => pht('Create Bot User'),
+ 'help' => pht('Create a new user for use with automated scripts.'),
+ );
+
+ $types[] = array(
+ 'type' => 'list',
+ 'name' => pht('Create Mailing List User'),
+ 'help' => pht(
+ 'Create a mailing list user to represent an existing, external '.
+ 'mailing list like a Google Group or a Mailman list.'),
+ );
+
+ $buttons = id(new AphrontFormRadioButtonControl())
+ ->setLabel(pht('Account Type'))
+ ->setName('type')
+ ->setValue($v_type);
+
+ foreach ($types as $type) {
+ $buttons->addButton($type['type'], $type['name'], $type['help']);
+ }
+
$form = id(new AphrontFormView())
->setUser($admin)
->appendRemarkupInstructions(
@@ -49,19 +82,7 @@
'explanation of user account types, see [[ %s | User Guide: '.
'Account Roles ]].',
PhabricatorEnv::getDoclink('User Guide: Account Roles')))
- ->appendChild(
- id(new AphrontFormRadioButtonControl())
- ->setLabel(pht('Account Type'))
- ->setName('type')
- ->setValue($v_type)
- ->addButton(
- 'standard',
- pht('Create Standard User'),
- hsprintf('%s<br /><br />%s', $standard_caption, $standard_admin))
- ->addButton(
- 'bot',
- pht('Create Bot/Script User'),
- hsprintf('%s<br /><br />%s', $bot_caption, $bot_admin)))
+ ->appendChild($buttons)
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($this->getApplicationURI())
diff --git a/src/applications/people/controller/PhabricatorPeopleListController.php b/src/applications/people/controller/PhabricatorPeopleListController.php
--- a/src/applications/people/controller/PhabricatorPeopleListController.php
+++ b/src/applications/people/controller/PhabricatorPeopleListController.php
@@ -33,20 +33,12 @@
$crumbs = parent::buildApplicationCrumbs();
$viewer = $this->getRequest()->getUser();
- $can_create = $this->hasApplicationCapability(
- PeopleCreateUsersCapability::CAPABILITY);
- if ($can_create) {
+ if ($viewer->getIsAdmin()) {
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create New User'))
->setHref($this->getApplicationURI('create/'))
->setIcon('fa-plus-square'));
- } else if ($viewer->getIsAdmin()) {
- $crumbs->addAction(
- id(new PHUIListItemView())
- ->setName(pht('Create New Bot'))
- ->setHref($this->getApplicationURI('new/bot/'))
- ->setIcon('fa-plus-square'));
}
return $crumbs;
diff --git a/src/applications/people/controller/PhabricatorPeopleNewController.php b/src/applications/people/controller/PhabricatorPeopleNewController.php
--- a/src/applications/people/controller/PhabricatorPeopleNewController.php
+++ b/src/applications/people/controller/PhabricatorPeopleNewController.php
@@ -7,15 +7,19 @@
$type = $request->getURIData('type');
$admin = $request->getUser();
+ $is_bot = false;
+ $is_list = false;
switch ($type) {
case 'standard':
$this->requireApplicationCapability(
PeopleCreateUsersCapability::CAPABILITY);
- $is_bot = false;
break;
case 'bot':
$is_bot = true;
break;
+ case 'list':
+ $is_list = true;
+ break;
default:
return new Aphront404Response();
}
@@ -77,8 +81,8 @@
// Automatically approve the user, since an admin is creating them.
$user->setIsApproved(1);
- // If the user is a bot, approve their email too.
- if ($is_bot) {
+ // If the user is a bot or list, approve their email too.
+ if ($is_bot || $is_list) {
$email->setIsVerified(1);
}
@@ -92,7 +96,13 @@
->makeSystemAgentUser($user, true);
}
- if ($welcome_checked && !$is_bot) {
+ if ($is_list) {
+ id(new PhabricatorUserEditor())
+ ->setActor($admin)
+ ->makeMailingListUser($user, true);
+ }
+
+ if ($welcome_checked && !$is_bot && !$is_list) {
$user->sendWelcomeEmail($admin);
}
@@ -123,7 +133,10 @@
if ($is_bot) {
$form->appendRemarkupInstructions(
- pht('You are creating a new **bot/script** user account.'));
+ pht('You are creating a new **bot** user account.'));
+ } else if ($is_list) {
+ $form->appendRemarkupInstructions(
+ pht('You are creating a new **mailing list** user account.'));
} else {
$form->appendRemarkupInstructions(
pht('You are creating a new **standard** user account.'));
@@ -150,7 +163,7 @@
->setCaption(PhabricatorUserEmail::describeAllowedAddresses())
->setError($e_email));
- if (!$is_bot) {
+ if (!$is_bot && !$is_list) {
$form->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
@@ -171,7 +184,7 @@
->appendChild(id(new AphrontFormDividerControl()))
->appendRemarkupInstructions(
pht(
- '**Why do bot/script accounts need an email address?**'.
+ '**Why do bot accounts need an email address?**'.
"\n\n".
'Although bots do not normally receive email from Phabricator, '.
'they can interact with other systems which require an email '.
diff --git a/src/applications/people/customfield/PhabricatorUserRolesField.php b/src/applications/people/customfield/PhabricatorUserRolesField.php
--- a/src/applications/people/customfield/PhabricatorUserRolesField.php
+++ b/src/applications/people/customfield/PhabricatorUserRolesField.php
@@ -37,6 +37,9 @@
if ($user->getIsSystemAgent()) {
$roles[] = pht('Bot');
}
+ if ($user->getIsMailingList()) {
+ $roles[] = pht('Mailing List');
+ }
if ($roles) {
return implode(', ', $roles);
diff --git a/src/applications/people/editor/PhabricatorUserEditor.php b/src/applications/people/editor/PhabricatorUserEditor.php
--- a/src/applications/people/editor/PhabricatorUserEditor.php
+++ b/src/applications/people/editor/PhabricatorUserEditor.php
@@ -278,6 +278,43 @@
return $this;
}
+ /**
+ * @task role
+ */
+ public function makeMailingListUser(PhabricatorUser $user, $mailing_list) {
+ $actor = $this->requireActor();
+
+ if (!$user->getID()) {
+ throw new Exception(pht('User has not been created yet!'));
+ }
+
+ $user->openTransaction();
+ $user->beginWriteLocking();
+
+ $user->reload();
+ if ($user->getIsMailingList() == $mailing_list) {
+ $user->endWriteLocking();
+ $user->killTransaction();
+ return $this;
+ }
+
+ $log = PhabricatorUserLog::initializeNewLog(
+ $actor,
+ $user->getPHID(),
+ PhabricatorUserLog::ACTION_MAILING_LIST);
+ $log->setOldValue($user->getIsMailingList());
+ $log->setNewValue($mailing_list);
+
+ $user->setIsMailingList((int)$mailing_list);
+ $user->save();
+
+ $log->save();
+
+ $user->endWriteLocking();
+ $user->saveTransaction();
+
+ return $this;
+ }
/**
* @task role
diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
--- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
+++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
@@ -44,6 +44,10 @@
$handle->setFullName($user->getFullName());
$handle->setImageURI($user->getProfileImageURI());
+ if ($user->getIsMailingList()) {
+ $handle->setIcon('fa-envelope-o');
+ }
+
$availability = null;
if (!$user->isUserActivated()) {
$availability = PhabricatorObjectHandle::AVAILABILITY_DISABLED;
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -12,6 +12,7 @@
private $dateCreatedBefore;
private $isAdmin;
private $isSystemAgent;
+ private $isMailingList;
private $isDisabled;
private $isApproved;
private $nameLike;
@@ -67,6 +68,11 @@
return $this;
}
+ public function withIsMailingList($mailing_list) {
+ $this->isMailingList = $mailing_list;
+ return $this;
+ }
+
public function withIsDisabled($disabled) {
$this->isDisabled = $disabled;
return $this;
@@ -340,6 +346,13 @@
(int)$this->isSystemAgent);
}
+ if ($this->isMailingList !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'user.isMailingList = %d',
+ (int)$this->isMailingList);
+ }
+
if (strlen($this->nameLike)) {
$where[] = qsprintf(
$conn_r,
diff --git a/src/applications/people/query/PhabricatorPeopleSearchEngine.php b/src/applications/people/query/PhabricatorPeopleSearchEngine.php
--- a/src/applications/people/query/PhabricatorPeopleSearchEngine.php
+++ b/src/applications/people/query/PhabricatorPeopleSearchEngine.php
@@ -34,6 +34,10 @@
$this->readBoolFromRequest($request, 'isSystemAgent'));
$saved->setParameter(
+ 'isMailingList',
+ $this->readBoolFromRequest($request, 'isMailingList'));
+
+ $saved->setParameter(
'needsApproval',
$this->readBoolFromRequest($request, 'needsApproval'));
@@ -77,6 +81,7 @@
$is_admin = $saved->getParameter('isAdmin');
$is_disabled = $saved->getParameter('isDisabled');
$is_system_agent = $saved->getParameter('isSystemAgent');
+ $is_mailing_list = $saved->getParameter('isMailingList');
$needs_approval = $saved->getParameter('needsApproval');
if ($is_admin !== null) {
@@ -91,6 +96,10 @@
$query->withIsSystemAgent($is_system_agent);
}
+ if ($is_mailing_list !== null) {
+ $query->withIsMailingList($is_mailing_list);
+ }
+
if ($needs_approval !== null) {
$query->withIsApproved(!$needs_approval);
}
@@ -121,6 +130,7 @@
$is_admin = $this->getBoolFromQuery($saved, 'isAdmin');
$is_disabled = $this->getBoolFromQuery($saved, 'isDisabled');
$is_system_agent = $this->getBoolFromQuery($saved, 'isSystemAgent');
+ $is_mailing_list = $this->getBoolFromQuery($saved, 'isMailingList');
$needs_approval = $this->getBoolFromQuery($saved, 'needsApproval');
$form
@@ -169,6 +179,17 @@
)))
->appendChild(
id(new AphrontFormSelectControl())
+ ->setName('isMailingList')
+ ->setLabel(pht('Mailing Lists'))
+ ->setValue($is_mailing_list)
+ ->setOptions(
+ array(
+ '' => pht('(Show All)'),
+ 'true' => pht('Show Only Mailing Lists'),
+ 'false' => pht('Hide Mailing Lists'),
+ )))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
->setName('needsApproval')
->setLabel(pht('Needs Approval'))
->setValue($needs_approval)
@@ -278,6 +299,10 @@
$item->addIcon('fa-desktop', pht('Bot'));
}
+ if ($user->getIsMailingList()) {
+ $item->addIcon('fa-envelope-o', pht('Mailing List'));
+ }
+
if ($viewer->getIsAdmin()) {
$user_id = $user->getID();
if ($is_approval) {
diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php
--- a/src/applications/people/storage/PhabricatorUser.php
+++ b/src/applications/people/storage/PhabricatorUser.php
@@ -38,6 +38,7 @@
protected $conduitCertificate;
protected $isSystemAgent = 0;
+ protected $isMailingList = 0;
protected $isAdmin = 0;
protected $isDisabled = 0;
protected $isEmailVerified = 0;
@@ -73,6 +74,8 @@
return (bool)$this->isDisabled;
case 'isSystemAgent':
return (bool)$this->isSystemAgent;
+ case 'isMailingList':
+ return (bool)$this->isMailingList;
case 'isEmailVerified':
return (bool)$this->isEmailVerified;
case 'isApproved':
@@ -112,6 +115,46 @@
return true;
}
+ public function canEstablishWebSessions() {
+ if (!$this->isUserActivated()) {
+ return false;
+ }
+
+ if ($this->getIsMailingList()) {
+ return false;
+ }
+
+ if ($this->getIsSystemAgent()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function canEstablishAPISessions() {
+ if (!$this->isUserActivated()) {
+ return false;
+ }
+
+ if ($this->getIsMailingList()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function canEstablishSSHSessions() {
+ if (!$this->isUserActivated()) {
+ return false;
+ }
+
+ if ($this->getIsMailingList()) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
* Returns `true` if this is a standard user who is logged in. Returns `false`
* for logged out, anonymous, or external users.
@@ -140,6 +183,7 @@
'consoleTab' => 'text64',
'conduitCertificate' => 'text255',
'isSystemAgent' => 'bool',
+ 'isMailingList' => 'bool',
'isDisabled' => 'bool',
'isAdmin' => 'bool',
'timezoneIdentifier' => 'text255',
@@ -1032,7 +1076,7 @@
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::POLICY_PUBLIC;
case PhabricatorPolicyCapability::CAN_EDIT:
- if ($this->getIsSystemAgent()) {
+ if ($this->getIsSystemAgent() || $this->getIsMailingList()) {
return PhabricatorPolicies::POLICY_ADMIN;
} else {
return PhabricatorPolicies::POLICY_NOONE;
diff --git a/src/applications/people/storage/PhabricatorUserLog.php b/src/applications/people/storage/PhabricatorUserLog.php
--- a/src/applications/people/storage/PhabricatorUserLog.php
+++ b/src/applications/people/storage/PhabricatorUserLog.php
@@ -16,6 +16,7 @@
const ACTION_ADMIN = 'admin';
const ACTION_SYSTEM_AGENT = 'system-agent';
+ const ACTION_MAILING_LIST = 'mailing-list';
const ACTION_DISABLE = 'disable';
const ACTION_APPROVE = 'approve';
const ACTION_DELETE = 'delete';
@@ -62,6 +63,7 @@
self::ACTION_EDIT => pht('Edit Account'),
self::ACTION_ADMIN => pht('Add/Remove Administrator'),
self::ACTION_SYSTEM_AGENT => pht('Add/Remove System Agent'),
+ self::ACTION_MAILING_LIST => pht('Add/Remove Mailing List'),
self::ACTION_DISABLE => pht('Enable/Disable'),
self::ACTION_APPROVE => pht('Approve Registration'),
self::ACTION_DELETE => pht('Delete User'),
diff --git a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php
--- a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php
+++ b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php
@@ -54,7 +54,9 @@
if ($user->getIsDisabled()) {
$closed = pht('Disabled');
} else if ($user->getIsSystemAgent()) {
- $closed = pht('Bot/Script');
+ $closed = pht('Bot');
+ } else if ($user->getIsMailingList()) {
+ $closed = pht('Mailing List');
}
$result = id(new PhabricatorTypeaheadResult())
@@ -65,6 +67,10 @@
->setPriorityType('user')
->setClosed($closed);
+ if ($user->getIsMailingList()) {
+ $result->setIcon('fa-envelope-o');
+ }
+
if ($this->enrichResults) {
$display_type = 'User';
if ($user->getIsAdmin()) {
diff --git a/src/applications/settings/controller/PhabricatorSettingsMainController.php b/src/applications/settings/controller/PhabricatorSettingsMainController.php
--- a/src/applications/settings/controller/PhabricatorSettingsMainController.php
+++ b/src/applications/settings/controller/PhabricatorSettingsMainController.php
@@ -97,6 +97,8 @@
$result = array();
foreach ($panels as $key => $panel) {
+ $panel->setUser($this->user);
+
if (!$panel->isEnabled()) {
continue;
}
diff --git a/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php b/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php
--- a/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php
+++ b/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php
@@ -19,6 +19,14 @@
return pht('Authentication');
}
+ public function isEnabled() {
+ if ($this->getUser()->getIsMailingList()) {
+ return false;
+ }
+
+ return true;
+ }
+
public function processRequest(AphrontRequest $request) {
$user = $this->getUser();
$viewer = $request->getUser();
diff --git a/src/applications/settings/panel/PhabricatorSSHKeysSettingsPanel.php b/src/applications/settings/panel/PhabricatorSSHKeysSettingsPanel.php
--- a/src/applications/settings/panel/PhabricatorSSHKeysSettingsPanel.php
+++ b/src/applications/settings/panel/PhabricatorSSHKeysSettingsPanel.php
@@ -19,6 +19,10 @@
}
public function isEnabled() {
+ if ($this->getUser()->getIsMailingList()) {
+ return false;
+ }
+
return true;
}

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 21, 8:31 PM (3 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6734377
Default Alt Text
D13123.diff (23 KB)

Event Timeline