1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 08:42:41 +01:00

Add "Auth Messages" to support customizing onboarding/welcome flows

Summary:
Ref T13222. Long ago, we had a Config option (`welcome.html`) to let you dump HTML onto the login screen, but this was relatively hard to use and not good from a security perspective.

In some cases this was obsoleted by Dashboards, but there's at least some remaining set of use cases for actual login instructions on the login screen. For example, WMF has some guidance on //which// SSO mechanism to use based on what types of account you have. On `secure`, users assume they can register by clicking "Log In With GitHub" or whatever, and it might reduce frustration to tell them upfront that registration is closed.

Some other types of auth messaging could also either use customization or defaults (e.g., the invite/welcome/approve mail).

We could do this with a bunch of Config options, but I'd generally like to move to a world where there's less stuff in Config and more configuration is contextual. I think it tends to be easier to use, and we get a lot of fringe benefits (granular permissions, API, normal transaction logs, more abililty to customize workflows and provide contextual help/hints, etc). Here, for example, we can provide a remarkup preview, which would be trickier with Config.

This does not actually do anything yet.

Test Plan: {F6137541}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13222

Differential Revision: https://secure.phabricator.com/D19992
This commit is contained in:
epriestley 2019-01-17 10:47:13 -08:00
parent ab7aceaabf
commit 2c713b2d25
22 changed files with 812 additions and 1 deletions

View file

@ -0,0 +1,8 @@
CREATE TABLE {$NAMESPACE}_auth.auth_message (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
messageKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
messageText LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,19 @@
CREATE TABLE {$NAMESPACE}_auth.auth_messagetransaction (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
authorPHID VARBINARY(64) NOT NULL,
objectPHID VARBINARY(64) NOT NULL,
viewPolicy VARBINARY(64) NOT NULL,
editPolicy VARBINARY(64) NOT NULL,
commentPHID VARBINARY(64) DEFAULT NULL,
commentVersion INT UNSIGNED NOT NULL,
transactionType VARCHAR(32) NOT NULL,
oldValue LONGTEXT NOT NULL,
newValue LONGTEXT NOT NULL,
contentSource LONGTEXT NOT NULL,
metadata LONGTEXT NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (`phid`),
KEY `key_object` (`objectPHID`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};

View file

@ -2246,6 +2246,7 @@ phutil_register_library_map(array(
'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php', 'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php',
'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php', 'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php',
'PhabricatorAuthLoginHandler' => 'applications/auth/handler/PhabricatorAuthLoginHandler.php', 'PhabricatorAuthLoginHandler' => 'applications/auth/handler/PhabricatorAuthLoginHandler.php',
'PhabricatorAuthLoginMessageType' => 'applications/auth/message/PhabricatorAuthLoginMessageType.php',
'PhabricatorAuthLogoutConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthLogoutConduitAPIMethod.php', 'PhabricatorAuthLogoutConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthLogoutConduitAPIMethod.php',
'PhabricatorAuthMFAEditEngineExtension' => 'applications/auth/engineextension/PhabricatorAuthMFAEditEngineExtension.php', 'PhabricatorAuthMFAEditEngineExtension' => 'applications/auth/engineextension/PhabricatorAuthMFAEditEngineExtension.php',
'PhabricatorAuthMainMenuBarExtension' => 'applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php', 'PhabricatorAuthMainMenuBarExtension' => 'applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php',
@ -2261,6 +2262,20 @@ phutil_register_library_map(array(
'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php',
'PhabricatorAuthManagementVerifyWorkflow' => 'applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php', 'PhabricatorAuthManagementVerifyWorkflow' => 'applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php',
'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php', 'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php',
'PhabricatorAuthMessage' => 'applications/auth/storage/PhabricatorAuthMessage.php',
'PhabricatorAuthMessageController' => 'applications/auth/controller/message/PhabricatorAuthMessageController.php',
'PhabricatorAuthMessageEditController' => 'applications/auth/controller/message/PhabricatorAuthMessageEditController.php',
'PhabricatorAuthMessageEditEngine' => 'applications/auth/editor/PhabricatorAuthMessageEditEngine.php',
'PhabricatorAuthMessageEditor' => 'applications/auth/editor/PhabricatorAuthMessageEditor.php',
'PhabricatorAuthMessageListController' => 'applications/auth/controller/message/PhabricatorAuthMessageListController.php',
'PhabricatorAuthMessagePHIDType' => 'applications/auth/phid/PhabricatorAuthMessagePHIDType.php',
'PhabricatorAuthMessageQuery' => 'applications/auth/query/PhabricatorAuthMessageQuery.php',
'PhabricatorAuthMessageTextTransaction' => 'applications/auth/xaction/PhabricatorAuthMessageTextTransaction.php',
'PhabricatorAuthMessageTransaction' => 'applications/auth/storage/PhabricatorAuthMessageTransaction.php',
'PhabricatorAuthMessageTransactionQuery' => 'applications/auth/query/PhabricatorAuthMessageTransactionQuery.php',
'PhabricatorAuthMessageTransactionType' => 'applications/auth/xaction/PhabricatorAuthMessageTransactionType.php',
'PhabricatorAuthMessageType' => 'applications/auth/message/PhabricatorAuthMessageType.php',
'PhabricatorAuthMessageViewController' => 'applications/auth/controller/message/PhabricatorAuthMessageViewController.php',
'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php',
'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php',
'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php', 'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php',
@ -2337,6 +2352,7 @@ phutil_register_library_map(array(
'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php', 'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php',
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php', 'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php', 'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
'PhabricatorAuthWelcomeMailMessageType' => 'applications/auth/message/PhabricatorAuthWelcomeMailMessageType.php',
'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php', 'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php',
'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.php', 'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.php',
'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php', 'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php',
@ -7920,6 +7936,7 @@ phutil_register_library_map(array(
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthLoginController' => 'PhabricatorAuthController', 'PhabricatorAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorAuthLoginHandler' => 'Phobject', 'PhabricatorAuthLoginHandler' => 'Phobject',
'PhabricatorAuthLoginMessageType' => 'PhabricatorAuthMessageType',
'PhabricatorAuthLogoutConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthLogoutConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod',
'PhabricatorAuthMFAEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorAuthMFAEditEngineExtension' => 'PhabricatorEditEngineExtension',
'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
@ -7935,6 +7952,25 @@ phutil_register_library_map(array(
'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorAuthMessage' => array(
'PhabricatorAuthDAO',
'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
),
'PhabricatorAuthMessageController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthMessageEditController' => 'PhabricatorAuthMessageController',
'PhabricatorAuthMessageEditEngine' => 'PhabricatorEditEngine',
'PhabricatorAuthMessageEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorAuthMessageListController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthMessagePHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthMessageTextTransaction' => 'PhabricatorAuthMessageTransactionType',
'PhabricatorAuthMessageTransaction' => 'PhabricatorModularTransaction',
'PhabricatorAuthMessageTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthMessageTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorAuthMessageType' => 'Phobject',
'PhabricatorAuthMessageViewController' => 'PhabricatorAuthMessageController',
'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController',
'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController',
'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController',
@ -8030,6 +8066,7 @@ phutil_register_library_map(array(
'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction', 'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction',
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController', 'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorAuthValidateController' => 'PhabricatorAuthController', 'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
'PhabricatorAuthWelcomeMailMessageType' => 'PhabricatorAuthMessageType',
'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAutoEventListener' => 'PhabricatorEventListener', 'PhabricatorAutoEventListener' => 'PhabricatorEventListener',
'PhabricatorBadgesApplication' => 'PhabricatorApplication', 'PhabricatorBadgesApplication' => 'PhabricatorApplication',

View file

@ -94,6 +94,16 @@ final class PhabricatorAuthApplication extends PhabricatorApplication {
'(?P<id>[1-9]\d*)/' => '(?P<id>[1-9]\d*)/' =>
'PhabricatorAuthFactorProviderViewController', 'PhabricatorAuthFactorProviderViewController',
), ),
'message/' => array(
$this->getQueryRoutePattern() =>
'PhabricatorAuthMessageListController',
$this->getEditRoutePattern('edit/') =>
'PhabricatorAuthMessageEditController',
'(?P<id>[1-9]\d*)/' =>
'PhabricatorAuthMessageViewController',
),
), ),
'/oauth/(?P<provider>\w+)/login/' '/oauth/(?P<provider>\w+)/login/'

View file

@ -31,6 +31,20 @@ abstract class PhabricatorAuthProviderController
->setHref($this->getApplicationURI('mfa/')) ->setHref($this->getApplicationURI('mfa/'))
->setIcon('fa-mobile')); ->setIcon('fa-mobile'));
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Onboarding'))
->setType(PHUIListItemView::TYPE_LABEL));
$nav->addMenuItem(
id(new PHUIListItemView())
->setKey('message')
->setName(pht('Customize Messages'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref($this->getApplicationURI('message/'))
->setIcon('fa-commenting-o'));
$nav->selectFilter(null); $nav->selectFilter(null);
return $nav; return $nav;

View file

@ -0,0 +1,11 @@
<?php
abstract class PhabricatorAuthMessageController
extends PhabricatorAuthProviderController {
protected function buildApplicationCrumbs() {
return parent::buildApplicationCrumbs()
->addTextCrumb(pht('Messages'), $this->getApplicationURI('message/'));
}
}

View file

@ -0,0 +1,31 @@
<?php
final class PhabricatorAuthMessageEditController
extends PhabricatorAuthMessageController {
public function handleRequest(AphrontRequest $request) {
$this->requireApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$engine = id(new PhabricatorAuthMessageEditEngine())
->setController($this);
$id = $request->getURIData('id');
if (!$id) {
$message_key = $request->getStr('messageKey');
$message_types = PhabricatorAuthMessageType::getAllMessageTypes();
$message_type = idx($message_types, $message_key);
if (!$message_type) {
return new Aphront404Response();
}
$engine
->addContextParameter('messageKey', $message_key)
->setMessageType($message_type);
}
return $engine->buildResponse();
}
}

View file

@ -0,0 +1,77 @@
<?php
final class PhabricatorAuthMessageListController
extends PhabricatorAuthProviderController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$can_manage = $this->hasApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$types = PhabricatorAuthMessageType::getAllMessageTypes();
$messages = id(new PhabricatorAuthMessageQuery())
->setViewer($viewer)
->execute();
$messages = mpull($messages, null, 'getMessageKey');
$list = new PHUIObjectItemListView();
foreach ($types as $type) {
$message = idx($messages, $type->getMessageTypeKey());
if ($message) {
$href = $message->getURI();
$name = $message->getMessageTypeDisplayName();
} else {
$href = '/auth/message/edit/?messageKey='.$type->getMessageTypeKey();
$name = $type->getDisplayName();
}
$item = id(new PHUIObjectItemView())
->setHeader($name)
->setHref($href)
->addAttribute($type->getShortDescription());
if ($message) {
$item->addIcon('fa-circle', pht('Customized'));
} else {
$item->addIcon('fa-circle-o grey', pht('Default'));
}
$list->addItem($item);
}
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb(pht('Messages'))
->setBorder(true);
$list->setFlush(true);
$list = id(new PHUIObjectBoxView())
->setHeaderText(pht('Auth Messages'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($list);
$title = pht('Auth Messages');
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon('fa-commenting-o');
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(
array(
$list,
));
$nav = $this->newNavigation()
->setCrumbs($crumbs)
->appendChild($view);
$nav->selectFilter('message');
return $this->newPage()
->setTitle($title)
->appendChild($nav);
}
}

View file

@ -0,0 +1,104 @@
<?php
final class PhabricatorAuthMessageViewController
extends PhabricatorAuthMessageController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$this->requireApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$message = id(new PhabricatorAuthMessageQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$message) {
return new Aphront404Response();
}
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($message->getObjectName())
->setBorder(true);
$header = $this->buildHeaderView($message);
$properties = $this->buildPropertiesView($message);
$curtain = $this->buildCurtain($message);
$timeline = $this->buildTransactionTimeline(
$message,
new PhabricatorAuthMessageTransactionQuery());
$timeline->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(
array(
$timeline,
))
->addPropertySection(pht('Details'), $properties);
return $this->newPage()
->setTitle($message->getMessageTypeDisplayName())
->setCrumbs($crumbs)
->setPageObjectPHIDs(
array(
$message->getPHID(),
))
->appendChild($view);
}
private function buildHeaderView(PhabricatorAuthMessage $message) {
$viewer = $this->getViewer();
$view = id(new PHUIHeaderView())
->setViewer($viewer)
->setHeader($message->getMessageTypeDisplayName());
return $view;
}
private function buildPropertiesView(PhabricatorAuthMessage $message) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setViewer($viewer);
$view->addProperty(
pht('Description'),
$message->getMessageType()->getShortDescription());
$view->addSectionHeader(
pht('Message Preview'),
PHUIPropertyListView::ICON_SUMMARY);
$view->addTextContent(
new PHUIRemarkupView($viewer, $message->getMessageText()));
return $view;
}
private function buildCurtain(PhabricatorAuthMessage $message) {
$viewer = $this->getViewer();
$id = $message->getID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$message,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain = $this->newCurtainView($message);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Message'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("message/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $curtain;
}
}

View file

@ -23,7 +23,7 @@ final class PhabricatorAuthFactorProviderEditController
$engine $engine
->addContextParameter('providerFactorKey', $factor_key) ->addContextParameter('providerFactorKey', $factor_key)
->setProviderFactor($factor); ->setProviderFactor($factor);
} }
return $engine->buildResponse(); return $engine->buildResponse();
} }

View file

@ -0,0 +1,108 @@
<?php
final class PhabricatorAuthMessageEditEngine
extends PhabricatorEditEngine {
private $messageType;
const ENGINECONST = 'auth.message';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Auth Messages');
}
public function getSummaryHeader() {
return pht('Edit Auth Messages');
}
public function getSummaryText() {
return pht('This engine is used to edit authentication messages.');
}
public function getEngineApplicationClass() {
return 'PhabricatorAuthApplication';
}
public function setMessageType(PhabricatorAuthMessageType $type) {
$this->messageType = $type;
return $this;
}
public function getMessageType() {
return $this->messageType;
}
protected function newEditableObject() {
$type = $this->getMessageType();
if ($type) {
$message = PhabricatorAuthMessage::initializeNewMessage($type);
} else {
$message = new PhabricatorAuthMessage();
}
return $message;
}
protected function newObjectQuery() {
return new PhabricatorAuthMessageQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Auth Message');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Auth Message');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Auth Message');
}
protected function getObjectEditShortText($object) {
return $object->getObjectName();
}
protected function getObjectCreateShortText() {
return pht('Create Auth Message');
}
protected function getObjectName() {
return pht('Auth Message');
}
protected function getEditorURI() {
return '/auth/message/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/auth/message/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AuthManageProvidersCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorRemarkupEditField())
->setKey('messageText')
->setTransactionType(
PhabricatorAuthMessageTextTransaction::TRANSACTIONTYPE)
->setLabel(pht('Message Text'))
->setDescription(pht('Custom text for the message.'))
->setValue($object->getMessageText()),
);
}
}

View file

@ -0,0 +1,22 @@
<?php
final class PhabricatorAuthMessageEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorAuthApplication';
}
public function getEditorObjectsDescription() {
return pht('Auth Messages');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this message.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthLoginMessageType
extends PhabricatorAuthMessageType {
const MESSAGEKEY = 'auth.login';
public function getDisplayName() {
return pht('Login Screen Instructions');
}
public function getShortDescription() {
return pht(
'Guidance shown on the main login screen before users log in or '.
'register.');
}
}

View file

@ -0,0 +1,32 @@
<?php
abstract class PhabricatorAuthMessageType
extends Phobject {
final public function getMessageTypeKey() {
return $this->getPhobjectClassConstant('MESSAGEKEY', 64);
}
final public static function getAllMessageTypes() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getMessageTypeKey')
->execute();
}
final public static function newFromKey($key) {
$types = self::getAllMessageTypes();
if (empty($types[$key])) {
throw new Exception(
pht(
'No message type exists with key "%s".',
$key));
}
return clone $types[$key];
}
abstract public function getDisplayName();
}

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthWelcomeMailMessageType
extends PhabricatorAuthMessageType {
const MESSAGEKEY = 'mail.welcome';
public function getDisplayName() {
return pht('Welcome Email Body');
}
public function getShortDescription() {
return pht(
'Custom instructions included in "Welcome" mail when an '.
'administrator creates a user account.');
}
}

View file

@ -0,0 +1,32 @@
<?php
final class PhabricatorAuthMessagePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AMSG';
public function getTypeName() {
return pht('Auth Message');
}
public function newObject() {
return new PhabricatorAuthMessage();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorAuthApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return new PhabricatorAuthMessageQuery();
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
return;
}
}

View file

@ -0,0 +1,83 @@
<?php
final class PhabricatorAuthMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $messageKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMessageKeys(array $keys) {
$this->messageKeys = $keys;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthMessage();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->messageKeys !== null) {
$where[] = qsprintf(
$conn,
'messageKey IN (%Ls)',
$this->messageKeys);
}
return $where;
}
protected function willFilterPage(array $messages) {
$message_types = PhabricatorAuthMessageType::getAllMessageTypes();
foreach ($messages as $key => $message) {
$message_key = $message->getMessageKey();
$message_type = idx($message_types, $message_key);
if (!$message_type) {
unset($messages[$key]);
$this->didRejectResult($message);
continue;
}
$message->attachMessageType($message_type);
}
return $messages;
}
public function getQueryApplicationClass() {
return 'PhabricatorAuthApplication';
}
}

View file

@ -0,0 +1,10 @@
<?php
final class PhabricatorAuthMessageTransactionQuery
extends PhabricatorApplicationTransactionQuery {
public function getTemplateApplicationTransaction() {
return new PhabricatorAuthMessageTransaction();
}
}

View file

@ -0,0 +1,116 @@
<?php
final class PhabricatorAuthMessage
extends PhabricatorAuthDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface {
protected $messageKey;
protected $messageText;
private $messageType = self::ATTACHABLE;
public static function initializeNewMessage(
PhabricatorAuthMessageType $type) {
return id(new self())
->setMessageKey($type->getMessageTypeKey())
->attachMessageType($type);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'messageKey' => 'text64',
'messageText' => 'text',
),
self::CONFIG_KEY_SCHEMA => array(
'key_type' => array(
'columns' => array('messageKey'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function getPHIDType() {
return PhabricatorAuthMessagePHIDType::TYPECONST;
}
public function getObjectName() {
return pht('Auth Message %d', $this->getID());
}
public function getURI() {
return urisprintf('/auth/message/%s', $this->getID());
}
public function attachMessageType(PhabricatorAuthMessageType $type) {
$this->messageType = $type;
return $this;
}
public function getMessageType() {
return $this->assertAttached($this->messageType);
}
public function getMessageTypeDisplayName() {
return $this->getMessageType()->getDisplayName();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::getMostOpenPolicy();
default:
return false;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
// Even if an install doesn't allow public users, you can still view
// auth messages: otherwise, we can't do things like show you
// guidance on the login screen.
return true;
default:
return false;
}
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorAuthMessageEditor();
}
public function getApplicationTransactionTemplate() {
return new PhabricatorAuthMessageTransaction();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->delete();
}
}

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthMessageTransaction
extends PhabricatorModularTransaction {
public function getApplicationName() {
return 'auth';
}
public function getApplicationTransactionType() {
return PhabricatorAuthMessagePHIDType::TYPECONST;
}
public function getBaseTransactionClass() {
return 'PhabricatorAuthMessageTransactionType';
}
}

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorAuthMessageTextTransaction
extends PhabricatorAuthMessageTransactionType {
const TRANSACTIONTYPE = 'text';
public function generateOldValue($object) {
return $object->getMessageText();
}
public function applyInternalEffects($object, $value) {
$object->setMessageText($value);
}
public function getTitle() {
return pht(
'%s updated the message text.',
$this->renderAuthor());
}
public function hasChangeDetailView() {
return true;
}
public function getMailDiffSectionHeader() {
return pht('CHANGES TO MESSAGE');
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class PhabricatorAuthMessageTransactionType
extends PhabricatorModularTransactionType {}