mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-05 20:31:03 +01:00
(stable) Promote 2019 Week 31
This commit is contained in:
commit
6f6ae61f00
128 changed files with 3071 additions and 1269 deletions
|
@ -10,7 +10,7 @@ return array(
|
|||
'conpherence.pkg.css' => '3c8a0668',
|
||||
'conpherence.pkg.js' => '020aebcf',
|
||||
'core.pkg.css' => 'af983028',
|
||||
'core.pkg.js' => '5a792749',
|
||||
'core.pkg.js' => '73a06a9f',
|
||||
'differential.pkg.css' => '8d8360fb',
|
||||
'differential.pkg.js' => '67e02996',
|
||||
'diffusion.pkg.css' => '42c75c37',
|
||||
|
@ -253,7 +253,7 @@ return array(
|
|||
'rsrc/externals/javelin/lib/URI.js' => '2e255291',
|
||||
'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb',
|
||||
'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e',
|
||||
'rsrc/externals/javelin/lib/Workflow.js' => '445e21a8',
|
||||
'rsrc/externals/javelin/lib/Workflow.js' => '945ff654',
|
||||
'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71',
|
||||
'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249',
|
||||
'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae',
|
||||
|
@ -412,16 +412,16 @@ return array(
|
|||
'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f',
|
||||
'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9',
|
||||
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172',
|
||||
'rsrc/js/application/projects/WorkboardBoard.js' => 'c02a5497',
|
||||
'rsrc/js/application/projects/WorkboardBoard.js' => 'b46d88c5',
|
||||
'rsrc/js/application/projects/WorkboardCard.js' => '0392a5d8',
|
||||
'rsrc/js/application/projects/WorkboardCardTemplate.js' => '2a61f8d4',
|
||||
'rsrc/js/application/projects/WorkboardCardTemplate.js' => '84f82dad',
|
||||
'rsrc/js/application/projects/WorkboardColumn.js' => 'c3d24e63',
|
||||
'rsrc/js/application/projects/WorkboardController.js' => '42c7a5a7',
|
||||
'rsrc/js/application/projects/WorkboardController.js' => 'b9d0c2f3',
|
||||
'rsrc/js/application/projects/WorkboardDropEffect.js' => '8e0aa661',
|
||||
'rsrc/js/application/projects/WorkboardHeader.js' => '111bfd2d',
|
||||
'rsrc/js/application/projects/WorkboardHeaderTemplate.js' => 'ebe83a6b',
|
||||
'rsrc/js/application/projects/WorkboardOrderTemplate.js' => '03e8891f',
|
||||
'rsrc/js/application/projects/behavior-project-boards.js' => 'aad45445',
|
||||
'rsrc/js/application/projects/behavior-project-boards.js' => '58cb6a88',
|
||||
'rsrc/js/application/projects/behavior-project-create.js' => '34c53422',
|
||||
'rsrc/js/application/projects/behavior-reorder-columns.js' => '8ac32fd9',
|
||||
'rsrc/js/application/releeph/releeph-preview-branch.js' => '75184d68',
|
||||
|
@ -667,7 +667,7 @@ return array(
|
|||
'javelin-behavior-phuix-example' => 'c2c500a7',
|
||||
'javelin-behavior-policy-control' => '0eaa33a9',
|
||||
'javelin-behavior-policy-rule-editor' => '9347f172',
|
||||
'javelin-behavior-project-boards' => 'aad45445',
|
||||
'javelin-behavior-project-boards' => '58cb6a88',
|
||||
'javelin-behavior-project-create' => '34c53422',
|
||||
'javelin-behavior-quicksand-blacklist' => '5a6f6a06',
|
||||
'javelin-behavior-read-only-warning' => 'b9109f8f',
|
||||
|
@ -743,16 +743,16 @@ return array(
|
|||
'javelin-view-renderer' => '9aae2b66',
|
||||
'javelin-view-visitor' => '308f9fe4',
|
||||
'javelin-websocket' => 'fdc13e4e',
|
||||
'javelin-workboard-board' => 'c02a5497',
|
||||
'javelin-workboard-board' => 'b46d88c5',
|
||||
'javelin-workboard-card' => '0392a5d8',
|
||||
'javelin-workboard-card-template' => '2a61f8d4',
|
||||
'javelin-workboard-card-template' => '84f82dad',
|
||||
'javelin-workboard-column' => 'c3d24e63',
|
||||
'javelin-workboard-controller' => '42c7a5a7',
|
||||
'javelin-workboard-controller' => 'b9d0c2f3',
|
||||
'javelin-workboard-drop-effect' => '8e0aa661',
|
||||
'javelin-workboard-header' => '111bfd2d',
|
||||
'javelin-workboard-header-template' => 'ebe83a6b',
|
||||
'javelin-workboard-order-template' => '03e8891f',
|
||||
'javelin-workflow' => '445e21a8',
|
||||
'javelin-workflow' => '945ff654',
|
||||
'maniphest-report-css' => '3d53188b',
|
||||
'maniphest-task-edit-css' => '272daa84',
|
||||
'maniphest-task-summary-css' => '61d1667e',
|
||||
|
@ -1133,9 +1133,6 @@ return array(
|
|||
'javelin-stratcom',
|
||||
'javelin-behavior',
|
||||
),
|
||||
'2a61f8d4' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
'2a8b62d9' => array(
|
||||
'multirow-row-manager',
|
||||
'javelin-install',
|
||||
|
@ -1264,16 +1261,6 @@ return array(
|
|||
'4234f572' => array(
|
||||
'syntax-default-css',
|
||||
),
|
||||
'42c7a5a7' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-vector',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'phabricator-drag-and-drop-file-upload',
|
||||
'javelin-workboard-board',
|
||||
),
|
||||
'4370900d' => array(
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
|
@ -1294,17 +1281,6 @@ return array(
|
|||
'43bc9360' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
'445e21a8' => array(
|
||||
'javelin-stratcom',
|
||||
'javelin-request',
|
||||
'javelin-dom',
|
||||
'javelin-vector',
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
'javelin-mask',
|
||||
'javelin-uri',
|
||||
'javelin-routable',
|
||||
),
|
||||
'46116c01' => array(
|
||||
'javelin-request',
|
||||
'javelin-behavior',
|
||||
|
@ -1423,6 +1399,16 @@ return array(
|
|||
'javelin-vector',
|
||||
'javelin-typeahead-static-source',
|
||||
),
|
||||
'58cb6a88' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-vector',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'javelin-workboard-controller',
|
||||
'javelin-workboard-drop-effect',
|
||||
),
|
||||
'5902260c' => array(
|
||||
'javelin-util',
|
||||
'javelin-magical-init',
|
||||
|
@ -1618,6 +1604,9 @@ return array(
|
|||
'javelin-resource',
|
||||
'javelin-routable',
|
||||
),
|
||||
'84f82dad' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
'87428eb2' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-diffusion-locate-file-source',
|
||||
|
@ -1709,6 +1698,17 @@ return array(
|
|||
'javelin-typeahead-preloaded-source',
|
||||
'javelin-util',
|
||||
),
|
||||
'945ff654' => array(
|
||||
'javelin-stratcom',
|
||||
'javelin-request',
|
||||
'javelin-dom',
|
||||
'javelin-vector',
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
'javelin-mask',
|
||||
'javelin-uri',
|
||||
'javelin-routable',
|
||||
),
|
||||
'94681e22' => array(
|
||||
'javelin-magical-init',
|
||||
'javelin-install',
|
||||
|
@ -1840,16 +1840,6 @@ return array(
|
|||
'javelin-dom',
|
||||
'javelin-util',
|
||||
),
|
||||
'aad45445' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-vector',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'javelin-workboard-controller',
|
||||
'javelin-workboard-drop-effect',
|
||||
),
|
||||
'ab85e184' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
|
@ -1898,6 +1888,18 @@ return array(
|
|||
'b347a301' => array(
|
||||
'javelin-behavior',
|
||||
),
|
||||
'b46d88c5' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'phabricator-draggable-list',
|
||||
'javelin-workboard-column',
|
||||
'javelin-workboard-header-template',
|
||||
'javelin-workboard-card-template',
|
||||
'javelin-workboard-order-template',
|
||||
),
|
||||
'b49fd60c' => array(
|
||||
'multirow-row-manager',
|
||||
'trigger-rule',
|
||||
|
@ -1940,20 +1942,18 @@ return array(
|
|||
'javelin-uri',
|
||||
'phabricator-notification',
|
||||
),
|
||||
'bde53589' => array(
|
||||
'phui-inline-comment-view-css',
|
||||
),
|
||||
'c02a5497' => array(
|
||||
'b9d0c2f3' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-vector',
|
||||
'javelin-stratcom',
|
||||
'javelin-workflow',
|
||||
'phabricator-draggable-list',
|
||||
'javelin-workboard-column',
|
||||
'javelin-workboard-header-template',
|
||||
'javelin-workboard-card-template',
|
||||
'javelin-workboard-order-template',
|
||||
'phabricator-drag-and-drop-file-upload',
|
||||
'javelin-workboard-board',
|
||||
),
|
||||
'bde53589' => array(
|
||||
'phui-inline-comment-view-css',
|
||||
),
|
||||
'c03f2fb4' => array(
|
||||
'javelin-install',
|
||||
|
|
2
resources/sql/autopatches/20190718.paste.01.edge.sql
Normal file
2
resources/sql/autopatches/20190718.paste.01.edge.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
RENAME TABLE {$NAMESPACE}_pastebin.edge
|
||||
TO {$NAMESPACE}_paste.edge;
|
2
resources/sql/autopatches/20190718.paste.02.edgedata.sql
Normal file
2
resources/sql/autopatches/20190718.paste.02.edgedata.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
RENAME TABLE {$NAMESPACE}_pastebin.edgedata
|
||||
TO {$NAMESPACE}_paste.edgedata;
|
2
resources/sql/autopatches/20190718.paste.03.paste.sql
Normal file
2
resources/sql/autopatches/20190718.paste.03.paste.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
RENAME TABLE {$NAMESPACE}_pastebin.pastebin_paste
|
||||
TO {$NAMESPACE}_paste.paste;
|
2
resources/sql/autopatches/20190718.paste.04.xaction.sql
Normal file
2
resources/sql/autopatches/20190718.paste.04.xaction.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
RENAME TABLE {$NAMESPACE}_pastebin.pastebin_pastetransaction
|
||||
TO {$NAMESPACE}_paste.paste_transaction;
|
2
resources/sql/autopatches/20190718.paste.05.comment.sql
Normal file
2
resources/sql/autopatches/20190718.paste.05.comment.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
RENAME TABLE {$NAMESPACE}_pastebin.pastebin_pastetransaction_comment
|
||||
TO {$NAMESPACE}_paste.paste_transaction_comment;
|
|
@ -2117,6 +2117,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorActionListView' => 'view/layout/PhabricatorActionListView.php',
|
||||
'PhabricatorActionView' => 'view/layout/PhabricatorActionView.php',
|
||||
'PhabricatorActivitySettingsPanel' => 'applications/settings/panel/PhabricatorActivitySettingsPanel.php',
|
||||
'PhabricatorAddEmailUserLogType' => 'applications/people/userlog/PhabricatorAddEmailUserLogType.php',
|
||||
'PhabricatorAddMultifactorUserLogType' => 'applications/people/userlog/PhabricatorAddMultifactorUserLogType.php',
|
||||
'PhabricatorAdministratorsPolicyRule' => 'applications/people/policyrule/PhabricatorAdministratorsPolicyRule.php',
|
||||
'PhabricatorAjaxRequestExceptionHandler' => 'aphront/handler/PhabricatorAjaxRequestExceptionHandler.php',
|
||||
'PhabricatorAlmanacApplication' => 'applications/almanac/application/PhabricatorAlmanacApplication.php',
|
||||
|
@ -2265,6 +2267,9 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthDisableController' => 'applications/auth/controller/config/PhabricatorAuthDisableController.php',
|
||||
'PhabricatorAuthDowngradeSessionController' => 'applications/auth/controller/PhabricatorAuthDowngradeSessionController.php',
|
||||
'PhabricatorAuthEditController' => 'applications/auth/controller/config/PhabricatorAuthEditController.php',
|
||||
'PhabricatorAuthEmailLoginAction' => 'applications/auth/action/PhabricatorAuthEmailLoginAction.php',
|
||||
'PhabricatorAuthEmailLoginMessageType' => 'applications/auth/message/PhabricatorAuthEmailLoginMessageType.php',
|
||||
'PhabricatorAuthEmailSetPasswordMessageType' => 'applications/auth/message/PhabricatorAuthEmailSetPasswordMessageType.php',
|
||||
'PhabricatorAuthFactor' => 'applications/auth/factor/PhabricatorAuthFactor.php',
|
||||
'PhabricatorAuthFactorConfig' => 'applications/auth/storage/PhabricatorAuthFactorConfig.php',
|
||||
'PhabricatorAuthFactorConfigQuery' => 'applications/auth/query/PhabricatorAuthFactorConfigQuery.php',
|
||||
|
@ -2426,7 +2431,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthTemporaryTokenTypeModule' => 'applications/auth/tokentype/PhabricatorAuthTemporaryTokenTypeModule.php',
|
||||
'PhabricatorAuthTerminateSessionController' => 'applications/auth/controller/PhabricatorAuthTerminateSessionController.php',
|
||||
'PhabricatorAuthTestSMSAction' => 'applications/auth/action/PhabricatorAuthTestSMSAction.php',
|
||||
'PhabricatorAuthTryEmailLoginAction' => 'applications/auth/action/PhabricatorAuthTryEmailLoginAction.php',
|
||||
'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php',
|
||||
'PhabricatorAuthTryPasswordAction' => 'applications/auth/action/PhabricatorAuthTryPasswordAction.php',
|
||||
'PhabricatorAuthTryPasswordWithoutCAPTCHAAction' => 'applications/auth/action/PhabricatorAuthTryPasswordWithoutCAPTCHAAction.php',
|
||||
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
|
||||
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
|
||||
'PhabricatorAuthWaitForApprovalMessageType' => 'applications/auth/message/PhabricatorAuthWaitForApprovalMessageType.php',
|
||||
|
@ -2662,6 +2670,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorCelerityApplication' => 'applications/celerity/application/PhabricatorCelerityApplication.php',
|
||||
'PhabricatorCelerityTestCase' => '__tests__/PhabricatorCelerityTestCase.php',
|
||||
'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php',
|
||||
'PhabricatorChangePasswordUserLogType' => 'applications/people/userlog/PhabricatorChangePasswordUserLogType.php',
|
||||
'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.php',
|
||||
'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php',
|
||||
'PhabricatorChartAxis' => 'applications/fact/chart/PhabricatorChartAxis.php',
|
||||
|
@ -2715,7 +2724,9 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
||||
'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php',
|
||||
'PhabricatorConduitCallManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitCallManagementWorkflow.php',
|
||||
'PhabricatorConduitCertificateFailureUserLogType' => 'applications/people/userlog/PhabricatorConduitCertificateFailureUserLogType.php',
|
||||
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
||||
'PhabricatorConduitCertificateUserLogType' => 'applications/people/userlog/PhabricatorConduitCertificateUserLogType.php',
|
||||
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
||||
'PhabricatorConduitContentSource' => 'infrastructure/contentsource/PhabricatorConduitContentSource.php',
|
||||
'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php',
|
||||
|
@ -3205,6 +3216,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEmailFormatSetting' => 'applications/settings/setting/PhabricatorEmailFormatSetting.php',
|
||||
'PhabricatorEmailFormatSettingsPanel' => 'applications/settings/panel/PhabricatorEmailFormatSettingsPanel.php',
|
||||
'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php',
|
||||
'PhabricatorEmailLoginUserLogType' => 'applications/people/userlog/PhabricatorEmailLoginUserLogType.php',
|
||||
'PhabricatorEmailNotificationsSetting' => 'applications/settings/setting/PhabricatorEmailNotificationsSetting.php',
|
||||
'PhabricatorEmailPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailPreferencesSettingsPanel.php',
|
||||
'PhabricatorEmailRePrefixSetting' => 'applications/settings/setting/PhabricatorEmailRePrefixSetting.php',
|
||||
|
@ -3218,6 +3230,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEmojiRemarkupRule' => 'applications/macro/markup/PhabricatorEmojiRemarkupRule.php',
|
||||
'PhabricatorEmojiTranslation' => 'infrastructure/internationalization/translation/PhabricatorEmojiTranslation.php',
|
||||
'PhabricatorEmptyQueryException' => 'infrastructure/query/exception/PhabricatorEmptyQueryException.php',
|
||||
'PhabricatorEnterHisecUserLogType' => 'applications/people/userlog/PhabricatorEnterHisecUserLogType.php',
|
||||
'PhabricatorEnumConfigType' => 'applications/config/type/PhabricatorEnumConfigType.php',
|
||||
'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php',
|
||||
'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php',
|
||||
|
@ -3230,6 +3243,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php',
|
||||
'PhabricatorExcelExportFormat' => 'infrastructure/export/format/PhabricatorExcelExportFormat.php',
|
||||
'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php',
|
||||
'PhabricatorExitHisecUserLogType' => 'applications/people/userlog/PhabricatorExitHisecUserLogType.php',
|
||||
'PhabricatorExportEngine' => 'infrastructure/export/engine/PhabricatorExportEngine.php',
|
||||
'PhabricatorExportEngineBulkJobType' => 'infrastructure/export/engine/PhabricatorExportEngineBulkJobType.php',
|
||||
'PhabricatorExportEngineExtension' => 'infrastructure/export/engine/PhabricatorExportEngineExtension.php',
|
||||
|
@ -3270,6 +3284,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFactObjectDimension' => 'applications/fact/storage/PhabricatorFactObjectDimension.php',
|
||||
'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php',
|
||||
'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php',
|
||||
'PhabricatorFailHisecUserLogType' => 'applications/people/userlog/PhabricatorFailHisecUserLogType.php',
|
||||
'PhabricatorFaviconRef' => 'applications/files/favicon/PhabricatorFaviconRef.php',
|
||||
'PhabricatorFaviconRefQuery' => 'applications/files/favicon/PhabricatorFaviconRefQuery.php',
|
||||
'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php',
|
||||
|
@ -3404,6 +3419,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFlaggableInterface' => 'applications/flag/interface/PhabricatorFlaggableInterface.php',
|
||||
'PhabricatorFlagsApplication' => 'applications/flag/application/PhabricatorFlagsApplication.php',
|
||||
'PhabricatorFlagsUIEventListener' => 'applications/flag/events/PhabricatorFlagsUIEventListener.php',
|
||||
'PhabricatorFullLoginUserLogType' => 'applications/people/userlog/PhabricatorFullLoginUserLogType.php',
|
||||
'PhabricatorFulltextEngine' => 'applications/search/index/PhabricatorFulltextEngine.php',
|
||||
'PhabricatorFulltextEngineExtension' => 'applications/search/index/PhabricatorFulltextEngineExtension.php',
|
||||
'PhabricatorFulltextEngineExtensionModule' => 'applications/search/index/PhabricatorFulltextEngineExtensionModule.php',
|
||||
|
@ -3542,7 +3558,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorLockLogManagementWorkflow' => 'applications/daemon/management/PhabricatorLockLogManagementWorkflow.php',
|
||||
'PhabricatorLockManagementWorkflow' => 'applications/daemon/management/PhabricatorLockManagementWorkflow.php',
|
||||
'PhabricatorLogTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorLogTriggerAction.php',
|
||||
'PhabricatorLoginFailureUserLogType' => 'applications/people/userlog/PhabricatorLoginFailureUserLogType.php',
|
||||
'PhabricatorLoginUserLogType' => 'applications/people/userlog/PhabricatorLoginUserLogType.php',
|
||||
'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php',
|
||||
'PhabricatorLogoutUserLogType' => 'applications/people/userlog/PhabricatorLogoutUserLogType.php',
|
||||
'PhabricatorLunarPhasePolicyRule' => 'applications/policy/rule/PhabricatorLunarPhasePolicyRule.php',
|
||||
'PhabricatorMacroApplication' => 'applications/macro/application/PhabricatorMacroApplication.php',
|
||||
'PhabricatorMacroAudioBehaviorTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php',
|
||||
|
@ -3951,6 +3970,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPackagesVersionViewController' => 'applications/packages/controller/PhabricatorPackagesVersionViewController.php',
|
||||
'PhabricatorPackagesView' => 'applications/packages/view/PhabricatorPackagesView.php',
|
||||
'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php',
|
||||
'PhabricatorPartialLoginUserLogType' => 'applications/people/userlog/PhabricatorPartialLoginUserLogType.php',
|
||||
'PhabricatorPassphraseApplication' => 'applications/passphrase/application/PhabricatorPassphraseApplication.php',
|
||||
'PhabricatorPasswordAuthProvider' => 'applications/auth/provider/PhabricatorPasswordAuthProvider.php',
|
||||
'PhabricatorPasswordDestructionEngineExtension' => 'applications/auth/extension/PhabricatorPasswordDestructionEngineExtension.php',
|
||||
|
@ -4001,6 +4021,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php',
|
||||
'PhabricatorPeopleDetailsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php',
|
||||
'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php',
|
||||
'PhabricatorPeopleEmailLoginMailEngine' => 'applications/people/mail/PhabricatorPeopleEmailLoginMailEngine.php',
|
||||
'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php',
|
||||
'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php',
|
||||
'PhabricatorPeopleIconSet' => 'applications/people/icon/PhabricatorPeopleIconSet.php',
|
||||
|
@ -4010,6 +4031,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
|
||||
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
|
||||
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
|
||||
'PhabricatorPeopleLogViewController' => 'applications/people/controller/PhabricatorPeopleLogViewController.php',
|
||||
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
|
||||
'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php',
|
||||
'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php',
|
||||
|
@ -4138,6 +4160,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php',
|
||||
'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php',
|
||||
'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php',
|
||||
'PhabricatorPrimaryEmailUserLogType' => 'applications/people/userlog/PhabricatorPrimaryEmailUserLogType.php',
|
||||
'PhabricatorProfileMenuEditEngine' => 'applications/search/editor/PhabricatorProfileMenuEditEngine.php',
|
||||
'PhabricatorProfileMenuEditor' => 'applications/search/editor/PhabricatorProfileMenuEditor.php',
|
||||
'PhabricatorProfileMenuEngine' => 'applications/search/engine/PhabricatorProfileMenuEngine.php',
|
||||
|
@ -4158,9 +4181,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php',
|
||||
'PhabricatorProjectBoardBackgroundController' => 'applications/project/controller/PhabricatorProjectBoardBackgroundController.php',
|
||||
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
|
||||
'PhabricatorProjectBoardDefaultController' => 'applications/project/controller/PhabricatorProjectBoardDefaultController.php',
|
||||
'PhabricatorProjectBoardDisableController' => 'applications/project/controller/PhabricatorProjectBoardDisableController.php',
|
||||
'PhabricatorProjectBoardFilterController' => 'applications/project/controller/PhabricatorProjectBoardFilterController.php',
|
||||
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
|
||||
'PhabricatorProjectBoardManageController' => 'applications/project/controller/PhabricatorProjectBoardManageController.php',
|
||||
'PhabricatorProjectBoardReloadController' => 'applications/project/controller/PhabricatorProjectBoardReloadController.php',
|
||||
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
|
||||
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
|
||||
'PhabricatorProjectBuiltinsExample' => 'applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php',
|
||||
|
@ -4170,6 +4196,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectColorsConfigType' => 'applications/project/config/PhabricatorProjectColorsConfigType.php',
|
||||
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
|
||||
'PhabricatorProjectColumnAuthorOrder' => 'applications/project/order/PhabricatorProjectColumnAuthorOrder.php',
|
||||
'PhabricatorProjectColumnBulkEditController' => 'applications/project/controller/PhabricatorProjectColumnBulkEditController.php',
|
||||
'PhabricatorProjectColumnBulkMoveController' => 'applications/project/controller/PhabricatorProjectColumnBulkMoveController.php',
|
||||
'PhabricatorProjectColumnCreatedOrder' => 'applications/project/order/PhabricatorProjectColumnCreatedOrder.php',
|
||||
'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php',
|
||||
'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php',
|
||||
|
@ -4196,6 +4224,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectColumnTransactionQuery' => 'applications/project/query/PhabricatorProjectColumnTransactionQuery.php',
|
||||
'PhabricatorProjectColumnTransactionType' => 'applications/project/xaction/column/PhabricatorProjectColumnTransactionType.php',
|
||||
'PhabricatorProjectColumnTriggerTransaction' => 'applications/project/xaction/column/PhabricatorProjectColumnTriggerTransaction.php',
|
||||
'PhabricatorProjectColumnViewQueryController' => 'applications/project/controller/PhabricatorProjectColumnViewQueryController.php',
|
||||
'PhabricatorProjectConfigOptions' => 'applications/project/config/PhabricatorProjectConfigOptions.php',
|
||||
'PhabricatorProjectConfiguredCustomField' => 'applications/project/customfield/PhabricatorProjectConfiguredCustomField.php',
|
||||
'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php',
|
||||
|
@ -4207,7 +4236,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectCustomFieldStringIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldStringIndex.php',
|
||||
'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php',
|
||||
'PhabricatorProjectDatasource' => 'applications/project/typeahead/PhabricatorProjectDatasource.php',
|
||||
'PhabricatorProjectDefaultController' => 'applications/project/controller/PhabricatorProjectDefaultController.php',
|
||||
'PhabricatorProjectDescriptionField' => 'applications/project/customfield/PhabricatorProjectDescriptionField.php',
|
||||
'PhabricatorProjectDetailsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php',
|
||||
'PhabricatorProjectDropEffect' => 'applications/project/icon/PhabricatorProjectDropEffect.php',
|
||||
|
@ -4356,6 +4384,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorQueryOrderTestCase' => 'infrastructure/query/order/__tests__/PhabricatorQueryOrderTestCase.php',
|
||||
'PhabricatorQueryOrderVector' => 'infrastructure/query/order/PhabricatorQueryOrderVector.php',
|
||||
'PhabricatorRateLimitRequestExceptionHandler' => 'aphront/handler/PhabricatorRateLimitRequestExceptionHandler.php',
|
||||
'PhabricatorReassignEmailUserLogType' => 'applications/people/userlog/PhabricatorReassignEmailUserLogType.php',
|
||||
'PhabricatorRebuildIndexesWorker' => 'applications/search/worker/PhabricatorRebuildIndexesWorker.php',
|
||||
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
|
||||
'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php',
|
||||
|
@ -4374,6 +4403,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRemarkupFigletBlockInterpreter' => 'infrastructure/markup/interpreter/PhabricatorRemarkupFigletBlockInterpreter.php',
|
||||
'PhabricatorRemarkupHyperlinkEngineExtension' => 'applications/remarkup/engineextension/PhabricatorRemarkupHyperlinkEngineExtension.php',
|
||||
'PhabricatorRemarkupUIExample' => 'applications/uiexample/examples/PhabricatorRemarkupUIExample.php',
|
||||
'PhabricatorRemoveEmailUserLogType' => 'applications/people/userlog/PhabricatorRemoveEmailUserLogType.php',
|
||||
'PhabricatorRemoveMultifactorUserLogType' => 'applications/people/userlog/PhabricatorRemoveMultifactorUserLogType.php',
|
||||
'PhabricatorRepositoriesSetupCheck' => 'applications/config/check/PhabricatorRepositoriesSetupCheck.php',
|
||||
'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php',
|
||||
'PhabricatorRepositoryActivateTransaction' => 'applications/repository/xaction/PhabricatorRepositoryActivateTransaction.php',
|
||||
|
@ -4512,6 +4543,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryVCSTransaction' => 'applications/repository/xaction/PhabricatorRepositoryVCSTransaction.php',
|
||||
'PhabricatorRepositoryWorkingCopyVersion' => 'applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php',
|
||||
'PhabricatorRequestExceptionHandler' => 'aphront/handler/PhabricatorRequestExceptionHandler.php',
|
||||
'PhabricatorResetPasswordUserLogType' => 'applications/people/userlog/PhabricatorResetPasswordUserLogType.php',
|
||||
'PhabricatorResourceSite' => 'aphront/site/PhabricatorResourceSite.php',
|
||||
'PhabricatorRobotsController' => 'applications/system/controller/PhabricatorRobotsController.php',
|
||||
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
|
||||
|
@ -4618,6 +4650,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorShiftChartFunction' => 'applications/fact/chart/PhabricatorShiftChartFunction.php',
|
||||
'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php',
|
||||
'PhabricatorShowFiletreeSetting' => 'applications/settings/setting/PhabricatorShowFiletreeSetting.php',
|
||||
'PhabricatorSignDocumentsUserLogType' => 'applications/people/userlog/PhabricatorSignDocumentsUserLogType.php',
|
||||
'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php',
|
||||
'PhabricatorSinChartFunction' => 'applications/fact/chart/PhabricatorSinChartFunction.php',
|
||||
'PhabricatorSite' => 'aphront/site/PhabricatorSite.php',
|
||||
|
@ -4908,6 +4941,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserFulltextEngine' => 'applications/people/search/PhabricatorUserFulltextEngine.php',
|
||||
'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php',
|
||||
'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php',
|
||||
'PhabricatorUserLogType' => 'applications/people/userlog/PhabricatorUserLogType.php',
|
||||
'PhabricatorUserLogTypeDatasource' => 'applications/people/typeahead/PhabricatorUserLogTypeDatasource.php',
|
||||
'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php',
|
||||
'PhabricatorUserMessageCountCacheType' => 'applications/people/cache/PhabricatorUserMessageCountCacheType.php',
|
||||
'PhabricatorUserNotificationCountCacheType' => 'applications/people/cache/PhabricatorUserNotificationCountCacheType.php',
|
||||
|
@ -4938,6 +4973,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUsersPolicyRule' => 'applications/people/policyrule/PhabricatorUsersPolicyRule.php',
|
||||
'PhabricatorUsersSearchField' => 'applications/people/searchfield/PhabricatorUsersSearchField.php',
|
||||
'PhabricatorVCSResponse' => 'applications/repository/response/PhabricatorVCSResponse.php',
|
||||
'PhabricatorVerifyEmailUserLogType' => 'applications/people/userlog/PhabricatorVerifyEmailUserLogType.php',
|
||||
'PhabricatorVersionedDraft' => 'applications/draft/storage/PhabricatorVersionedDraft.php',
|
||||
'PhabricatorVeryWowEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorVeryWowEnglishTranslation.php',
|
||||
'PhabricatorVideoDocumentEngine' => 'applications/files/document/PhabricatorVideoDocumentEngine.php',
|
||||
|
@ -4949,6 +4985,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorWeekStartDaySetting' => 'applications/settings/setting/PhabricatorWeekStartDaySetting.php',
|
||||
'PhabricatorWildConfigType' => 'applications/config/type/PhabricatorWildConfigType.php',
|
||||
'PhabricatorWordPressAuthProvider' => 'applications/auth/provider/PhabricatorWordPressAuthProvider.php',
|
||||
'PhabricatorWorkboardViewState' => 'applications/project/state/PhabricatorWorkboardViewState.php',
|
||||
'PhabricatorWorker' => 'infrastructure/daemon/workers/PhabricatorWorker.php',
|
||||
'PhabricatorWorkerActiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerActiveTask.php',
|
||||
'PhabricatorWorkerActiveTaskQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerActiveTaskQuery.php',
|
||||
|
@ -5017,6 +5054,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorXHProfSampleQuery' => 'applications/xhprof/query/PhabricatorXHProfSampleQuery.php',
|
||||
'PhabricatorXHProfSampleSearchEngine' => 'applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php',
|
||||
'PhabricatorYoutubeRemarkupRule' => 'infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php',
|
||||
'PhabricatorZipSetupCheck' => 'applications/config/check/PhabricatorZipSetupCheck.php',
|
||||
'Phame404Response' => 'applications/phame/site/Phame404Response.php',
|
||||
'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
|
||||
'PhameBlog404Controller' => 'applications/phame/controller/blog/PhameBlog404Controller.php',
|
||||
|
@ -5576,6 +5614,7 @@ phutil_register_library_map(array(
|
|||
'SlowvoteEmbedView' => 'applications/slowvote/view/SlowvoteEmbedView.php',
|
||||
'SlowvoteInfoConduitAPIMethod' => 'applications/slowvote/conduit/SlowvoteInfoConduitAPIMethod.php',
|
||||
'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php',
|
||||
'SlowvoteSearchConduitAPIMethod' => 'applications/slowvote/conduit/SlowvoteSearchConduitAPIMethod.php',
|
||||
'SubscriptionListDialogBuilder' => 'applications/subscriptions/view/SubscriptionListDialogBuilder.php',
|
||||
'SubscriptionListStringBuilder' => 'applications/subscriptions/view/SubscriptionListStringBuilder.php',
|
||||
'TokenConduitAPIMethod' => 'applications/tokens/conduit/TokenConduitAPIMethod.php',
|
||||
|
@ -8037,6 +8076,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorActionListView' => 'AphrontTagView',
|
||||
'PhabricatorActionView' => 'AphrontView',
|
||||
'PhabricatorActivitySettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorAddEmailUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorAddMultifactorUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorAdministratorsPolicyRule' => 'PhabricatorPolicyRule',
|
||||
'PhabricatorAjaxRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
|
||||
'PhabricatorAlmanacApplication' => 'PhabricatorApplication',
|
||||
|
@ -8212,6 +8253,9 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthDisableController' => 'PhabricatorAuthProviderConfigController',
|
||||
'PhabricatorAuthDowngradeSessionController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthEditController' => 'PhabricatorAuthProviderConfigController',
|
||||
'PhabricatorAuthEmailLoginAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthEmailLoginMessageType' => 'PhabricatorAuthMessageType',
|
||||
'PhabricatorAuthEmailSetPasswordMessageType' => 'PhabricatorAuthMessageType',
|
||||
'PhabricatorAuthFactor' => 'Phobject',
|
||||
'PhabricatorAuthFactorConfig' => array(
|
||||
'PhabricatorAuthDAO',
|
||||
|
@ -8410,7 +8454,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthTemporaryTokenTypeModule' => 'PhabricatorConfigModule',
|
||||
'PhabricatorAuthTerminateSessionController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthTestSMSAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryEmailLoginAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryPasswordAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryPasswordWithoutCAPTCHAAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthWaitForApprovalMessageType' => 'PhabricatorAuthMessageType',
|
||||
|
@ -8696,6 +8743,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorCelerityApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorCelerityTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase',
|
||||
'PhabricatorChangePasswordUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger',
|
||||
'PhabricatorChangesetResponse' => 'AphrontProxyResponse',
|
||||
'PhabricatorChartAxis' => 'Phobject',
|
||||
|
@ -8754,7 +8802,9 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorConduitCallManagementWorkflow' => 'PhabricatorConduitManagementWorkflow',
|
||||
'PhabricatorConduitCertificateFailureUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
||||
'PhabricatorConduitCertificateUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitContentSource' => 'PhabricatorContentSource',
|
||||
'PhabricatorConduitController' => 'PhabricatorController',
|
||||
|
@ -9296,6 +9346,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEmailFormatSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEmailFormatSettingsPanel' => 'PhabricatorEditEngineSettingsPanel',
|
||||
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
|
||||
'PhabricatorEmailLoginUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorEmailNotificationsSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEmailPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorEmailRePrefixSetting' => 'PhabricatorSelectSetting',
|
||||
|
@ -9309,6 +9360,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEmojiRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'PhabricatorEmojiTranslation' => 'PhutilTranslation',
|
||||
'PhabricatorEmptyQueryException' => 'Exception',
|
||||
'PhabricatorEnterHisecUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorEnumConfigType' => 'PhabricatorTextConfigType',
|
||||
'PhabricatorEnv' => 'Phobject',
|
||||
'PhabricatorEnvTestCase' => 'PhabricatorTestCase',
|
||||
|
@ -9321,6 +9373,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorExampleEventListener' => 'PhabricatorEventListener',
|
||||
'PhabricatorExcelExportFormat' => 'PhabricatorExportFormat',
|
||||
'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource',
|
||||
'PhabricatorExitHisecUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorExportEngine' => 'Phobject',
|
||||
'PhabricatorExportEngineBulkJobType' => 'PhabricatorWorkerSingleBulkJobType',
|
||||
'PhabricatorExportEngineExtension' => 'Phobject',
|
||||
|
@ -9366,6 +9419,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFactObjectDimension' => 'PhabricatorFactDimension',
|
||||
'PhabricatorFactRaw' => 'PhabricatorFactDAO',
|
||||
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
|
||||
'PhabricatorFailHisecUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorFaviconRef' => 'Phobject',
|
||||
'PhabricatorFaviconRefQuery' => 'Phobject',
|
||||
'PhabricatorFavoritesApplication' => 'PhabricatorApplication',
|
||||
|
@ -9537,6 +9591,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFlaggableInterface' => 'PhabricatorPHIDInterface',
|
||||
'PhabricatorFlagsApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorFlagsUIEventListener' => 'PhabricatorEventListener',
|
||||
'PhabricatorFullLoginUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorFulltextEngine' => 'Phobject',
|
||||
'PhabricatorFulltextEngineExtension' => 'Phobject',
|
||||
'PhabricatorFulltextEngineExtensionModule' => 'PhabricatorConfigModule',
|
||||
|
@ -9682,7 +9737,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorLockLogManagementWorkflow' => 'PhabricatorLockManagementWorkflow',
|
||||
'PhabricatorLockManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorLogTriggerAction' => 'PhabricatorTriggerAction',
|
||||
'PhabricatorLoginFailureUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorLoginUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorLogoutController' => 'PhabricatorAuthController',
|
||||
'PhabricatorLogoutUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorLunarPhasePolicyRule' => 'PhabricatorPolicyRule',
|
||||
'PhabricatorMacroApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorMacroAudioBehaviorTransaction' => 'PhabricatorMacroTransactionType',
|
||||
|
@ -10162,6 +10220,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPackagesVersionViewController' => 'PhabricatorPackagesVersionController',
|
||||
'PhabricatorPackagesView' => 'AphrontView',
|
||||
'PhabricatorPagerUIExample' => 'PhabricatorUIExample',
|
||||
'PhabricatorPartialLoginUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorPassphraseApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorPasswordAuthProvider' => 'PhabricatorAuthProvider',
|
||||
'PhabricatorPasswordDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
|
||||
|
@ -10224,6 +10283,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
||||
'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleEmailLoginMailEngine' => 'PhabricatorPeopleMailEngine',
|
||||
'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorPeopleIconSet' => 'PhabricatorIconSet',
|
||||
|
@ -10233,6 +10293,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorPeopleLogViewController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleMailEngine' => 'Phobject',
|
||||
'PhabricatorPeopleMailEngineException' => 'Exception',
|
||||
|
@ -10381,6 +10442,7 @@ phutil_register_library_map(array(
|
|||
),
|
||||
'PhabricatorPolicyType' => 'PhabricatorPolicyConstants',
|
||||
'PhabricatorPonderApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorPrimaryEmailUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorProfileMenuEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorProfileMenuEngine' => 'Phobject',
|
||||
|
@ -10421,9 +10483,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectArchiveController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectBoardBackgroundController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectBoardDefaultController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardFilterController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardManageController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardReloadController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectBuiltinsExample' => 'PhabricatorUIExample',
|
||||
|
@ -10440,6 +10505,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitResultInterface',
|
||||
),
|
||||
'PhabricatorProjectColumnAuthorOrder' => 'PhabricatorProjectColumnOrder',
|
||||
'PhabricatorProjectColumnBulkEditController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectColumnBulkMoveController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectColumnCreatedOrder' => 'PhabricatorProjectColumnOrder',
|
||||
'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController',
|
||||
|
@ -10469,6 +10536,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectColumnTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhabricatorProjectColumnTransactionType' => 'PhabricatorModularTransactionType',
|
||||
'PhabricatorProjectColumnTriggerTransaction' => 'PhabricatorProjectColumnTransactionType',
|
||||
'PhabricatorProjectColumnViewQueryController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorProjectConfiguredCustomField' => array(
|
||||
'PhabricatorProjectStandardCustomField',
|
||||
|
@ -10483,7 +10551,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
|
||||
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorProjectDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorProjectDefaultController' => 'PhabricatorProjectBoardController',
|
||||
'PhabricatorProjectDescriptionField' => 'PhabricatorProjectStandardCustomField',
|
||||
'PhabricatorProjectDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
||||
'PhabricatorProjectDropEffect' => 'Phobject',
|
||||
|
@ -10643,6 +10710,7 @@ phutil_register_library_map(array(
|
|||
'Iterator',
|
||||
),
|
||||
'PhabricatorRateLimitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
|
||||
'PhabricatorReassignEmailUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorRebuildIndexesWorker' => 'PhabricatorWorker',
|
||||
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorRedirectController' => 'PhabricatorController',
|
||||
|
@ -10661,6 +10729,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRemarkupFigletBlockInterpreter' => 'PhutilRemarkupBlockInterpreter',
|
||||
'PhabricatorRemarkupHyperlinkEngineExtension' => 'PhutilRemarkupHyperlinkEngineExtension',
|
||||
'PhabricatorRemarkupUIExample' => 'PhabricatorUIExample',
|
||||
'PhabricatorRemoveEmailUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorRemoveMultifactorUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorRepositoriesSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorRepository' => array(
|
||||
'PhabricatorRepositoryDAO',
|
||||
|
@ -10868,6 +10938,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryVCSTransaction' => 'PhabricatorRepositoryTransactionType',
|
||||
'PhabricatorRepositoryWorkingCopyVersion' => 'PhabricatorRepositoryDAO',
|
||||
'PhabricatorRequestExceptionHandler' => 'AphrontRequestExceptionHandler',
|
||||
'PhabricatorResetPasswordUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorResourceSite' => 'PhabricatorSite',
|
||||
'PhabricatorRobotsController' => 'PhabricatorController',
|
||||
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||
|
@ -10976,6 +11047,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorShiftChartFunction' => 'PhabricatorChartFunction',
|
||||
'PhabricatorShortSite' => 'PhabricatorSite',
|
||||
'PhabricatorShowFiletreeSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorSignDocumentsUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorSimpleEditType' => 'PhabricatorEditType',
|
||||
'PhabricatorSinChartFunction' => 'PhabricatorChartFunction',
|
||||
'PhabricatorSite' => 'AphrontSite',
|
||||
|
@ -11004,6 +11076,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorSpacesInterface',
|
||||
'PhabricatorConduitResultInterface',
|
||||
),
|
||||
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
|
||||
'PhabricatorSlowvotePollPHIDType' => 'PhabricatorPHIDType',
|
||||
|
@ -11310,6 +11383,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorUserLogType' => 'Phobject',
|
||||
'PhabricatorUserLogTypeDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorUserLogView' => 'AphrontView',
|
||||
'PhabricatorUserMessageCountCacheType' => 'PhabricatorUserCacheType',
|
||||
'PhabricatorUserNotificationCountCacheType' => 'PhabricatorUserCacheType',
|
||||
|
@ -11345,6 +11420,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUsersPolicyRule' => 'PhabricatorPolicyRule',
|
||||
'PhabricatorUsersSearchField' => 'PhabricatorSearchTokenizerField',
|
||||
'PhabricatorVCSResponse' => 'AphrontResponse',
|
||||
'PhabricatorVerifyEmailUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorVersionedDraft' => 'PhabricatorDraftDAO',
|
||||
'PhabricatorVeryWowEnglishTranslation' => 'PhutilTranslation',
|
||||
'PhabricatorVideoDocumentEngine' => 'PhabricatorDocumentEngine',
|
||||
|
@ -11356,6 +11432,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorWeekStartDaySetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorWildConfigType' => 'PhabricatorJSONConfigType',
|
||||
'PhabricatorWordPressAuthProvider' => 'PhabricatorOAuth2AuthProvider',
|
||||
'PhabricatorWorkboardViewState' => 'Phobject',
|
||||
'PhabricatorWorker' => 'Phobject',
|
||||
'PhabricatorWorkerActiveTask' => 'PhabricatorWorkerTask',
|
||||
'PhabricatorWorkerActiveTaskQuery' => 'PhabricatorWorkerTaskQuery',
|
||||
|
@ -11437,6 +11514,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorXHProfSampleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorXHProfSampleSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorYoutubeRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'PhabricatorZipSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'Phame404Response' => 'AphrontHTMLResponse',
|
||||
'PhameBlog' => array(
|
||||
'PhameDAO',
|
||||
|
@ -12145,6 +12223,7 @@ phutil_register_library_map(array(
|
|||
'SlowvoteEmbedView' => 'AphrontView',
|
||||
'SlowvoteInfoConduitAPIMethod' => 'SlowvoteConduitAPIMethod',
|
||||
'SlowvoteRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||
'SlowvoteSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||
'SubscriptionListDialogBuilder' => 'Phobject',
|
||||
'SubscriptionListStringBuilder' => 'Phobject',
|
||||
'TokenConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
|
|
|
@ -5,10 +5,6 @@ final class PhabricatorAuthChangePasswordAction
|
|||
|
||||
const TYPECONST = 'auth.password';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 20 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthEmailLoginAction extends PhabricatorSystemAction {
|
||||
|
||||
const TYPECONST = 'mail.login';
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 3 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
||||
public function getLimitExplanation() {
|
||||
return pht(
|
||||
'Too many account recovery email links have been sent to this account '.
|
||||
'in a short period of time.');
|
||||
}
|
||||
|
||||
}
|
|
@ -4,10 +4,6 @@ final class PhabricatorAuthNewFactorAction extends PhabricatorSystemAction {
|
|||
|
||||
const TYPECONST = 'auth.factor.new';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 60 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
|
|
@ -4,10 +4,6 @@ final class PhabricatorAuthTestSMSAction extends PhabricatorSystemAction {
|
|||
|
||||
const TYPECONST = 'auth.sms.test';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 60 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthTryEmailLoginAction
|
||||
extends PhabricatorSystemAction {
|
||||
|
||||
const TYPECONST = 'mail.try-login';
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 20 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
||||
public function getLimitExplanation() {
|
||||
return pht(
|
||||
'You have made too many account recovery requests in a short period '.
|
||||
'of time.');
|
||||
}
|
||||
|
||||
}
|
|
@ -4,10 +4,6 @@ final class PhabricatorAuthTryFactorAction extends PhabricatorSystemAction {
|
|||
|
||||
const TYPECONST = 'auth.factor';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 10 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthTryPasswordAction
|
||||
extends PhabricatorSystemAction {
|
||||
|
||||
const TYPECONST = 'auth.password';
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 100 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
||||
public function getLimitExplanation() {
|
||||
return pht(
|
||||
'Your remote address has made too many login attempts in a short '.
|
||||
'period of time.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthTryPasswordWithoutCAPTCHAAction
|
||||
extends PhabricatorSystemAction {
|
||||
|
||||
const TYPECONST = 'auth.password-without-captcha';
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 10 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
||||
}
|
|
@ -108,7 +108,7 @@ final class PhabricatorAuthApplication extends PhabricatorApplication {
|
|||
'PhabricatorAuthMessageListController',
|
||||
$this->getEditRoutePattern('edit/') =>
|
||||
'PhabricatorAuthMessageEditController',
|
||||
'(?P<id>[1-9]\d*)/' =>
|
||||
'(?P<id>[^/]+)/' =>
|
||||
'PhabricatorAuthMessageViewController',
|
||||
),
|
||||
|
||||
|
|
|
@ -53,6 +53,14 @@ final class PhabricatorEmailLoginController
|
|||
// it expensive to fish for valid email addresses while giving the user
|
||||
// a better error if they goof their email.
|
||||
|
||||
$action_actor = PhabricatorSystemActionEngine::newActorFromRequest(
|
||||
$request);
|
||||
|
||||
PhabricatorSystemActionEngine::willTakeAction(
|
||||
array($action_actor),
|
||||
new PhabricatorAuthTryEmailLoginAction(),
|
||||
1);
|
||||
|
||||
$target_email = id(new PhabricatorUserEmail())->loadOneWhere(
|
||||
'address = %s',
|
||||
$v_email);
|
||||
|
@ -94,29 +102,40 @@ final class PhabricatorEmailLoginController
|
|||
}
|
||||
|
||||
if (!$errors) {
|
||||
$body = $this->newAccountLoginMailBody(
|
||||
$target_user,
|
||||
$is_logged_in);
|
||||
$target_address = new PhutilEmailAddress($target_email->getAddress());
|
||||
|
||||
$user_log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$target_user->getPHID(),
|
||||
PhabricatorEmailLoginUserLogType::LOGTYPE);
|
||||
|
||||
$mail_engine = id(new PhabricatorPeopleEmailLoginMailEngine())
|
||||
->setSender($viewer)
|
||||
->setRecipient($target_user)
|
||||
->setRecipientAddress($target_address)
|
||||
->setActivityLog($user_log);
|
||||
|
||||
try {
|
||||
$mail_engine->validateMail();
|
||||
} catch (PhabricatorPeopleMailEngineException $ex) {
|
||||
return $this->newDialog()
|
||||
->setTitle($ex->getTitle())
|
||||
->appendParagraph($ex->getBody())
|
||||
->addCancelButton('/auth/start/', pht('Done'));
|
||||
}
|
||||
|
||||
$mail_engine->sendMail();
|
||||
|
||||
if ($is_logged_in) {
|
||||
$subject = pht('[Phabricator] Account Password Link');
|
||||
$instructions = pht(
|
||||
'An email has been sent containing a link you can use to set '.
|
||||
'a password for your account.');
|
||||
} else {
|
||||
$subject = pht('[Phabricator] Account Login Link');
|
||||
$instructions = pht(
|
||||
'An email has been sent containing a link you can use to log '.
|
||||
'in to your account.');
|
||||
}
|
||||
|
||||
$mail = id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->setForceDelivery(true)
|
||||
->addRawTos(array($target_email->getAddress()))
|
||||
->setBody($body)
|
||||
->saveAndSend();
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Check Your Email'))
|
||||
->setShortTitle(pht('Email Sent'))
|
||||
|
@ -182,55 +201,6 @@ final class PhabricatorEmailLoginController
|
|||
->addSubmitButton(pht('Send Email'));
|
||||
}
|
||||
|
||||
private function newAccountLoginMailBody(
|
||||
PhabricatorUser $user,
|
||||
$is_logged_in) {
|
||||
|
||||
$engine = new PhabricatorAuthSessionEngine();
|
||||
$uri = $engine->getOneTimeLoginURI(
|
||||
$user,
|
||||
null,
|
||||
PhabricatorAuthSessionEngine::ONETIME_RESET);
|
||||
|
||||
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||
$have_passwords = $this->isPasswordAuthEnabled();
|
||||
|
||||
if ($have_passwords) {
|
||||
if ($is_logged_in) {
|
||||
$body = pht(
|
||||
'You can use this link to set a password on your account:'.
|
||||
"\n\n %s\n",
|
||||
$uri);
|
||||
} else if ($is_serious) {
|
||||
$body = pht(
|
||||
"You can use this link to reset your Phabricator password:".
|
||||
"\n\n %s\n",
|
||||
$uri);
|
||||
} else {
|
||||
$body = pht(
|
||||
"Condolences on forgetting your password. You can use this ".
|
||||
"link to reset it:\n\n".
|
||||
" %s\n\n".
|
||||
"After you set a new password, consider writing it down on a ".
|
||||
"sticky note and attaching it to your monitor so you don't ".
|
||||
"forget again! Choosing a very short, easy-to-remember password ".
|
||||
"like \"cat\" or \"1234\" might also help.\n\n".
|
||||
"Best Wishes,\nPhabricator\n",
|
||||
$uri);
|
||||
|
||||
}
|
||||
} else {
|
||||
$body = pht(
|
||||
"You can use this login link to regain access to your Phabricator ".
|
||||
"account:".
|
||||
"\n\n".
|
||||
" %s\n",
|
||||
$uri);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function isPasswordAuthEnabled() {
|
||||
return (bool)PhabricatorPasswordAuthProvider::getPasswordProvider();
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ final class PhabricatorAuthEditController
|
|||
}
|
||||
|
||||
$errors = array();
|
||||
$validation_exception = null;
|
||||
|
||||
$v_login = $config->getShouldAllowLogin();
|
||||
$v_registration = $config->getShouldAllowRegistration();
|
||||
|
@ -153,12 +154,16 @@ final class PhabricatorAuthEditController
|
|||
$editor = id(new PhabricatorAuthProviderConfigEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->applyTransactions($config, $xactions);
|
||||
->setContinueOnNoEffect(true);
|
||||
|
||||
$next_uri = $config->getURI();
|
||||
try {
|
||||
$editor->applyTransactions($config, $xactions);
|
||||
$next_uri = $config->getURI();
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($next_uri);
|
||||
return id(new AphrontRedirectResponse())->setURI($next_uri);
|
||||
} catch (Exception $ex) {
|
||||
$validation_exception = $ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$properties = $provider->readFormValuesFromProvider();
|
||||
|
@ -325,12 +330,35 @@ final class PhabricatorAuthEditController
|
|||
|
||||
$provider->extendEditForm($request, $form, $properties, $issues);
|
||||
|
||||
$locked_config_key = 'auth.lock-config';
|
||||
$is_locked = PhabricatorEnv::getEnvConfig($locked_config_key);
|
||||
|
||||
$locked_warning = null;
|
||||
if ($is_locked && !$validation_exception) {
|
||||
$message = pht(
|
||||
'Authentication provider configuration is locked, and can not be '.
|
||||
'changed without being unlocked. See the configuration setting %s '.
|
||||
'for details.',
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/config/edit/'.$locked_config_key,
|
||||
),
|
||||
$locked_config_key));
|
||||
$locked_warning = id(new PHUIInfoView())
|
||||
->setViewer($viewer)
|
||||
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||
->setErrors(array($message));
|
||||
}
|
||||
|
||||
$form
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($cancel_uri)
|
||||
->setDisabled($is_locked)
|
||||
->setValue($button));
|
||||
|
||||
|
||||
$help = $provider->getConfigurationHelp();
|
||||
if ($help) {
|
||||
$form->appendChild(id(new PHUIFormDividerControl()));
|
||||
|
@ -346,12 +374,16 @@ final class PhabricatorAuthEditController
|
|||
$form_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Provider'))
|
||||
->setFormErrors($errors)
|
||||
->setValidationException($validation_exception)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->setForm($form);
|
||||
|
||||
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter(array(
|
||||
$locked_warning,
|
||||
$form_box,
|
||||
$footer,
|
||||
));
|
||||
|
|
|
@ -78,12 +78,14 @@ final class PhabricatorAuthListController
|
|||
->setGuidanceContext($guidance_context)
|
||||
->newInfoView();
|
||||
|
||||
$is_disabled = (!$can_manage || $is_locked);
|
||||
$button = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setButtonType(PHUIButtonView::BUTTONTYPE_SIMPLE)
|
||||
->setHref($this->getApplicationURI('config/new/'))
|
||||
->setIcon('fa-plus')
|
||||
->setDisabled(!$can_manage || $is_locked)
|
||||
->setDisabled($is_disabled)
|
||||
->setWorkflow($is_disabled)
|
||||
->setHref($this->getApplicationURI('config/new/'))
|
||||
->setText(pht('Add Provider'));
|
||||
|
||||
$list->setFlush(true);
|
||||
|
|
|
@ -9,6 +9,27 @@ final class PhabricatorAuthNewController
|
|||
|
||||
$viewer = $this->getViewer();
|
||||
$cancel_uri = $this->getApplicationURI();
|
||||
$locked_config_key = 'auth.lock-config';
|
||||
$is_locked = PhabricatorEnv::getEnvConfig($locked_config_key);
|
||||
|
||||
if ($is_locked) {
|
||||
$message = pht(
|
||||
'Authentication provider configuration is locked, and can not be '.
|
||||
'changed without being unlocked. See the configuration setting %s '.
|
||||
'for details.',
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/config/edit/'.$locked_config_key,
|
||||
),
|
||||
$locked_config_key));
|
||||
|
||||
return $this->newDialog()
|
||||
->setUser($viewer)
|
||||
->setTitle(pht('Authentication Config Locked'))
|
||||
->appendChild($message)
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
|
||||
$providers = PhabricatorAuthProvider::getAllBaseProviders();
|
||||
|
||||
|
|
|
@ -114,6 +114,86 @@ final class PhabricatorAuthProviderViewController
|
|||
pht('Provider Type'),
|
||||
$config->getProvider()->getProviderName());
|
||||
|
||||
$status = $this->buildStatus($config);
|
||||
$view->addProperty(pht('Status'), $status);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
private function buildStatus(PhabricatorAuthProviderConfig $config) {
|
||||
$viewer = $this->getViewer();
|
||||
$view = id(new PHUIStatusListView())
|
||||
->setViewer($viewer);
|
||||
|
||||
$icon_enabled = PHUIStatusItemView::ICON_ACCEPT;
|
||||
$icon_disabled = PHUIStatusItemView::ICON_REJECT;
|
||||
|
||||
$icon_map = array(
|
||||
true => $icon_enabled,
|
||||
false => $icon_disabled,
|
||||
);
|
||||
|
||||
$color_map = array(
|
||||
true => 'green',
|
||||
false => 'red',
|
||||
);
|
||||
|
||||
$provider = $config->getProvider();
|
||||
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getIsEnabled()],
|
||||
$color_map[$config->getIsEnabled()])
|
||||
->setTarget(pht('Provider Enabled')));
|
||||
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getShouldAllowLogin()],
|
||||
$color_map[$config->getShouldAllowLogin()])
|
||||
->setTarget(pht('Allow Logins')));
|
||||
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getShouldAllowRegistration()],
|
||||
$color_map[$config->getShouldAllowRegistration()])
|
||||
->setTarget(pht('Allow Registration')));
|
||||
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getShouldAllowLink()],
|
||||
$color_map[$config->getShouldAllowLink()])
|
||||
->setTarget(pht('Allow Account Linking')));
|
||||
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getShouldAllowUnlink()],
|
||||
$color_map[$config->getShouldAllowUnlink()])
|
||||
->setTarget(pht('Allow Account Unlinking')));
|
||||
|
||||
if ($provider->shouldAllowEmailTrustConfiguration()) {
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getShouldTrustEmails()],
|
||||
$color_map[$config->getShouldTrustEmails()])
|
||||
->setTarget(pht('Trust Email Addresses')));
|
||||
}
|
||||
|
||||
if ($provider->supportsAutoLogin()) {
|
||||
$view->addItem(
|
||||
id(new PHUIStatusItemView())
|
||||
->setIcon(
|
||||
$icon_map[$config->getShouldAutoLogin()],
|
||||
$color_map[$config->getShouldAutoLogin()])
|
||||
->setTarget(pht('Allow Auto Login')));
|
||||
}
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,14 @@ final class PhabricatorAuthMessageListController
|
|||
$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();
|
||||
$href = urisprintf(
|
||||
'/auth/message/%s/',
|
||||
$type->getMessageTypeKey());
|
||||
$name = $type->getDisplayName();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,26 +9,61 @@ final class PhabricatorAuthMessageViewController
|
|||
$this->requireApplicationCapability(
|
||||
AuthManageProvidersCapability::CAPABILITY);
|
||||
|
||||
$message = id(new PhabricatorAuthMessageQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($request->getURIData('id')))
|
||||
->executeOne();
|
||||
if (!$message) {
|
||||
return new Aphront404Response();
|
||||
// The "id" in the URI may either be an actual storage record ID (if a
|
||||
// message has already been created) or a message type key (for a message
|
||||
// type which does not have a record yet).
|
||||
|
||||
// This flow allows messages which have not been set yet to have a detail
|
||||
// page (so users can get detailed information about the message and see
|
||||
// any default value).
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
if (ctype_digit($id)) {
|
||||
$message = id(new PhabricatorAuthMessageQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$message) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
} else {
|
||||
$types = PhabricatorAuthMessageType::getAllMessageTypes();
|
||||
if (!isset($types[$id])) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
// If this message type already has a storage record, redirect to the
|
||||
// canonical page for the record.
|
||||
$message = id(new PhabricatorAuthMessageQuery())
|
||||
->setViewer($viewer)
|
||||
->withMessageKeys(array($id))
|
||||
->executeOne();
|
||||
if ($message) {
|
||||
$message_uri = $message->getURI();
|
||||
return id(new AphrontRedirectResponse())->setURI($message_uri);
|
||||
}
|
||||
|
||||
// Otherwise, create an empty placeholder message object with the
|
||||
// appropriate message type.
|
||||
$message = PhabricatorAuthMessage::initializeNewMessage($types[$id]);
|
||||
}
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($message->getObjectName())
|
||||
->addTextCrumb($message->getMessageType()->getDisplayName())
|
||||
->setBorder(true);
|
||||
|
||||
$header = $this->buildHeaderView($message);
|
||||
$properties = $this->buildPropertiesView($message);
|
||||
$curtain = $this->buildCurtain($message);
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$message,
|
||||
new PhabricatorAuthMessageTransactionQuery());
|
||||
$timeline->setShouldTerminate(true);
|
||||
if ($message->getID()) {
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$message,
|
||||
new PhabricatorAuthMessageTransactionQuery());
|
||||
$timeline->setShouldTerminate(true);
|
||||
} else {
|
||||
$timeline = null;
|
||||
}
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
|
@ -62,19 +97,36 @@ final class PhabricatorAuthMessageViewController
|
|||
private function buildPropertiesView(PhabricatorAuthMessage $message) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$message_type = $message->getMessageType();
|
||||
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setViewer($viewer);
|
||||
|
||||
$view->addProperty(
|
||||
pht('Description'),
|
||||
$message->getMessageType()->getShortDescription());
|
||||
$full_description = $message_type->getFullDescription();
|
||||
if (strlen($full_description)) {
|
||||
$view->addTextContent(new PHUIRemarkupView($viewer, $full_description));
|
||||
} else {
|
||||
$short_description = $message_type->getShortDescription();
|
||||
$view->addProperty(pht('Description'), $short_description);
|
||||
}
|
||||
|
||||
$view->addSectionHeader(
|
||||
pht('Message Preview'),
|
||||
PHUIPropertyListView::ICON_SUMMARY);
|
||||
$message_text = $message->getMessageText();
|
||||
if (strlen($message_text)) {
|
||||
$view->addSectionHeader(
|
||||
pht('Message Preview'),
|
||||
PHUIPropertyListView::ICON_SUMMARY);
|
||||
|
||||
$view->addTextContent(
|
||||
new PHUIRemarkupView($viewer, $message->getMessageText()));
|
||||
$view->addTextContent(new PHUIRemarkupView($viewer, $message_text));
|
||||
}
|
||||
|
||||
$default_text = $message_type->getDefaultMessageText();
|
||||
if (strlen($default_text)) {
|
||||
$view->addSectionHeader(
|
||||
pht('Default Message'),
|
||||
PHUIPropertyListView::ICON_SUMMARY);
|
||||
|
||||
$view->addTextContent(new PHUIRemarkupView($viewer, $default_text));
|
||||
}
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
@ -88,13 +140,27 @@ final class PhabricatorAuthMessageViewController
|
|||
$message,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
if ($id) {
|
||||
$edit_uri = urisprintf('message/edit/%s/', $id);
|
||||
$edit_name = pht('Edit Message');
|
||||
} else {
|
||||
$edit_uri = urisprintf('message/edit/');
|
||||
$params = array(
|
||||
'messageKey' => $message->getMessageKey(),
|
||||
);
|
||||
$edit_uri = new PhutilURI($edit_uri, $params);
|
||||
|
||||
$edit_name = pht('Customize Message');
|
||||
}
|
||||
$edit_uri = $this->getApplicationURI($edit_uri);
|
||||
|
||||
$curtain = $this->newCurtainView($message);
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Message'))
|
||||
->setName($edit_name)
|
||||
->setIcon('fa-pencil')
|
||||
->setHref($this->getApplicationURI("message/edit/{$id}/"))
|
||||
->setHref($edit_uri)
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
|
|
|
@ -125,4 +125,25 @@ final class PhabricatorAuthProviderConfigEditor
|
|||
return parent::mergeTransactions($u, $v);
|
||||
}
|
||||
|
||||
protected function validateAllTransactions(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
|
||||
$errors = parent::validateAllTransactions($object, $xactions);
|
||||
|
||||
$locked_config_key = 'auth.lock-config';
|
||||
$is_locked = PhabricatorEnv::getEnvConfig($locked_config_key);
|
||||
|
||||
if ($is_locked) {
|
||||
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
||||
null,
|
||||
pht('Config Locked'),
|
||||
pht('Authentication provider configuration is locked, and can not be '.
|
||||
'changed without being unlocked.'),
|
||||
null);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -294,8 +294,8 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
null,
|
||||
$identity_phid,
|
||||
($partial
|
||||
? PhabricatorUserLog::ACTION_LOGIN_PARTIAL
|
||||
: PhabricatorUserLog::ACTION_LOGIN));
|
||||
? PhabricatorPartialLoginUserLogType::LOGTYPE
|
||||
: PhabricatorLoginUserLogType::LOGTYPE));
|
||||
|
||||
$log->setDetails(
|
||||
array(
|
||||
|
@ -366,7 +366,7 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$user,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_LOGOUT);
|
||||
PhabricatorLogoutUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
|
||||
$extensions = PhabricatorAuthSessionEngineExtension::getAllExtensions();
|
||||
|
@ -688,13 +688,13 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_ENTER_HISEC);
|
||||
PhabricatorEnterHisecUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
} else {
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_FAIL_HISEC);
|
||||
PhabricatorFailHisecUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
|
@ -831,7 +831,7 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EXIT_HISEC);
|
||||
PhabricatorExitHisecUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
}
|
||||
|
||||
|
@ -872,7 +872,7 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_LOGIN_FULL);
|
||||
PhabricatorFullLoginUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
unset($unguarded);
|
||||
}
|
||||
|
@ -917,7 +917,7 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_LOGIN_LEGALPAD);
|
||||
PhabricatorSignDocumentsUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
}
|
||||
unset($unguarded);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthEmailLoginMessageType
|
||||
extends PhabricatorAuthMessageType {
|
||||
|
||||
const MESSAGEKEY = 'mail.login';
|
||||
|
||||
public function getDisplayName() {
|
||||
return pht('Mail Body: Email Login');
|
||||
}
|
||||
|
||||
public function getShortDescription() {
|
||||
return pht(
|
||||
'Guidance in the message body when users request an email link '.
|
||||
'to access their account.');
|
||||
}
|
||||
|
||||
public function getFullDescription() {
|
||||
return pht(
|
||||
'Guidance included in the mail message body when users request an '.
|
||||
'email link to access their account.'.
|
||||
"\n\n".
|
||||
'For installs with password authentication enabled, users access this '.
|
||||
'workflow by using the "Forgot your password?" link on the login '.
|
||||
'screen.'.
|
||||
"\n\n".
|
||||
'For installs without password authentication enabled, users access '.
|
||||
'this workflow by using the "Send a login link to your email address." '.
|
||||
'link on the login screen. This workflow allows users to recover '.
|
||||
'access to their account if there is an issue with an external '.
|
||||
'login service.');
|
||||
}
|
||||
|
||||
public function getDefaultMessageText() {
|
||||
return pht(
|
||||
'You (or someone pretending to be you) recently requested an account '.
|
||||
'recovery link be sent to this email address. If you did not make '.
|
||||
'this request, you can ignore this message.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthEmailSetPasswordMessageType
|
||||
extends PhabricatorAuthMessageType {
|
||||
|
||||
const MESSAGEKEY = 'mail.set-password';
|
||||
|
||||
public function getDisplayName() {
|
||||
return pht('Mail Body: Set Password');
|
||||
}
|
||||
|
||||
public function getShortDescription() {
|
||||
return pht(
|
||||
'Guidance in the message body when users set a password on an account '.
|
||||
'which did not previously have a password.');
|
||||
}
|
||||
|
||||
}
|
|
@ -28,5 +28,14 @@ abstract class PhabricatorAuthMessageType
|
|||
}
|
||||
|
||||
abstract public function getDisplayName();
|
||||
abstract public function getShortDescription();
|
||||
|
||||
public function getFullDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getDefaultMessageText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ final class PhabricatorAuthWelcomeMailMessageType
|
|||
const MESSAGEKEY = 'mail.welcome';
|
||||
|
||||
public function getDisplayName() {
|
||||
return pht('Welcome Email Body');
|
||||
return pht('Mail Body: Welcome');
|
||||
}
|
||||
|
||||
public function getShortDescription() {
|
||||
|
|
|
@ -255,48 +255,29 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
|
|||
$viewer = $request->getUser();
|
||||
$content_source = PhabricatorContentSource::newFromRequest($request);
|
||||
|
||||
$captcha_limit = 5;
|
||||
$hard_limit = 32;
|
||||
$limit_window = phutil_units('15 minutes in seconds');
|
||||
$rate_actor = PhabricatorSystemActionEngine::newActorFromRequest($request);
|
||||
|
||||
$failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP(
|
||||
PhabricatorUserLog::ACTION_LOGIN_FAILURE,
|
||||
$limit_window);
|
||||
PhabricatorSystemActionEngine::willTakeAction(
|
||||
array($rate_actor),
|
||||
new PhabricatorAuthTryPasswordAction(),
|
||||
1);
|
||||
|
||||
// If the same remote address has submitted several failed login attempts
|
||||
// recently, require they provide a CAPTCHA response for new attempts.
|
||||
$require_captcha = false;
|
||||
$captcha_valid = false;
|
||||
if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) {
|
||||
if (count($failed_attempts) > $captcha_limit) {
|
||||
try {
|
||||
PhabricatorSystemActionEngine::willTakeAction(
|
||||
array($rate_actor),
|
||||
new PhabricatorAuthTryPasswordWithoutCAPTCHAAction(),
|
||||
1);
|
||||
} catch (PhabricatorSystemActionRateLimitException $ex) {
|
||||
$require_captcha = true;
|
||||
$captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request);
|
||||
}
|
||||
}
|
||||
|
||||
// If the user has submitted quite a few failed login attempts recently,
|
||||
// give them a hard limit.
|
||||
if (count($failed_attempts) > $hard_limit) {
|
||||
$guidance = array();
|
||||
|
||||
$guidance[] = pht(
|
||||
'Your remote address has failed too many login attempts recently. '.
|
||||
'Wait a few minutes before trying again.');
|
||||
|
||||
$guidance[] = pht(
|
||||
'If you are unable to log in to your account, you can '.
|
||||
'[[ /login/email | send a reset link to your email address ]].');
|
||||
|
||||
$guidance = implode("\n\n", $guidance);
|
||||
|
||||
$dialog = $controller->newDialog()
|
||||
->setTitle(pht('Too Many Login Attempts'))
|
||||
->appendChild(new PHUIRemarkupView($viewer, $guidance))
|
||||
->addCancelButton('/auth/start/', pht('Wait Patiently'));
|
||||
|
||||
return array(null, $dialog);
|
||||
}
|
||||
|
||||
$response = null;
|
||||
$account = null;
|
||||
$log_user = null;
|
||||
|
@ -337,7 +318,7 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
null,
|
||||
$log_user ? $log_user->getPHID() : null,
|
||||
PhabricatorUserLog::ACTION_LOGIN_FAILURE);
|
||||
PhabricatorLoginFailureUserLogType::LOGTYPE);
|
||||
$log->save();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ final class PhabricatorAuthMessage
|
|||
}
|
||||
|
||||
public function getURI() {
|
||||
return urisprintf('/auth/message/%s', $this->getID());
|
||||
return urisprintf('/auth/message/%s/', $this->getID());
|
||||
}
|
||||
|
||||
public function attachMessageType(PhabricatorAuthMessageType $type) {
|
||||
|
@ -75,12 +75,16 @@ final class PhabricatorAuthMessage
|
|||
$message_key) {
|
||||
|
||||
$message = self::loadMessage($viewer, $message_key);
|
||||
|
||||
if (!$message) {
|
||||
return null;
|
||||
if ($message) {
|
||||
$message_text = $message->getMessageText();
|
||||
if (strlen($message_text)) {
|
||||
return $message_text;
|
||||
}
|
||||
}
|
||||
|
||||
return $message->getMessageText();
|
||||
$message_type = PhabricatorAuthMessageType::newFromKey($message_key);
|
||||
|
||||
return $message_type->getDefaultMessageText();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,15 +14,8 @@ final class PhabricatorAuthProviderConfigTransaction
|
|||
|
||||
const PROPERTY_KEY = 'auth:property';
|
||||
|
||||
private $provider;
|
||||
|
||||
public function setProvider(PhabricatorAuthProvider $provider) {
|
||||
$this->provider = $provider;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProvider() {
|
||||
return $this->provider;
|
||||
return $this->getObject()->getProvider();
|
||||
}
|
||||
|
||||
public function getApplicationName() {
|
||||
|
|
|
@ -41,7 +41,7 @@ final class ConduitGetCertificateConduitAPIMethod extends ConduitAPIMethod {
|
|||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP(
|
||||
PhabricatorUserLog::ACTION_CONDUIT_CERTIFICATE_FAILURE,
|
||||
PhabricatorConduitCertificateFailureUserLogType::LOGTYPE,
|
||||
60 * 5);
|
||||
|
||||
if (count($failed_attempts) > 5) {
|
||||
|
@ -61,7 +61,7 @@ final class ConduitGetCertificateConduitAPIMethod extends ConduitAPIMethod {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$request->getUser(),
|
||||
$info->getUserPHID(),
|
||||
PhabricatorUserLog::ACTION_CONDUIT_CERTIFICATE)
|
||||
PhabricatorConduitCertificateUserLogType::LOGTYPE)
|
||||
->save();
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ final class ConduitGetCertificateConduitAPIMethod extends ConduitAPIMethod {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$request->getUser(),
|
||||
$info ? $info->getUserPHID() : '-',
|
||||
PhabricatorUserLog::ACTION_CONDUIT_CERTIFICATE_FAILURE)
|
||||
PhabricatorConduitCertificateFailureUserLogType::LOGTYPE)
|
||||
->save();
|
||||
}
|
||||
|
||||
|
|
29
src/applications/config/check/PhabricatorZipSetupCheck.php
Normal file
29
src/applications/config/check/PhabricatorZipSetupCheck.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorZipSetupCheck extends PhabricatorSetupCheck {
|
||||
|
||||
public function getDefaultGroup() {
|
||||
return self::GROUP_OTHER;
|
||||
}
|
||||
|
||||
protected function executeChecks() {
|
||||
if (!extension_loaded('zip')) {
|
||||
$message = pht(
|
||||
'The PHP "zip" extension is not installed. This extension is '.
|
||||
'required by certain data export operations, including exporting '.
|
||||
'data to Excel.'.
|
||||
"\n\n".
|
||||
'To clear this setup issue, install the extension and restart your '.
|
||||
'webserver.'.
|
||||
"\n\n".
|
||||
'You may safely ignore this issue if you do not plan to export '.
|
||||
'data in Zip archives or Excel spreadsheets, or intend to install '.
|
||||
'the extension later.');
|
||||
|
||||
$this->newIssue('extension.zip')
|
||||
->setName(pht('Missing "zip" Extension'))
|
||||
->setMessage($message)
|
||||
->addPHPExtension('zip');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ final class PhabricatorDaemonManagementStatusWorkflow
|
|||
'instance ("%s").',
|
||||
$instance));
|
||||
} else {
|
||||
$this->writeInfo(
|
||||
$this->logInfo(
|
||||
pht('NO DAEMONS'),
|
||||
pht('There are no running daemon processes.'));
|
||||
}
|
||||
|
|
|
@ -7,17 +7,6 @@ abstract class DiffusionQueryConduitAPIMethod
|
|||
return true;
|
||||
}
|
||||
|
||||
public function getMethodStatus() {
|
||||
return self::METHOD_STATUS_UNSTABLE;
|
||||
}
|
||||
|
||||
public function getMethodStatusDescription() {
|
||||
return pht(
|
||||
'See T2784 - migrating Diffusion working copy calls to conduit methods. '.
|
||||
'Until that task is completed (and possibly after) these methods are '.
|
||||
'unstable.');
|
||||
}
|
||||
|
||||
private $diffusionRequest;
|
||||
private $repository;
|
||||
|
||||
|
|
|
@ -5,10 +5,6 @@ final class PhabricatorFilesOutboundRequestAction
|
|||
|
||||
const TYPECONST = 'files.outbound';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 60 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ final class PhabricatorFlagQuery
|
|||
const GROUP_COLOR = 'color';
|
||||
const GROUP_NONE = 'none';
|
||||
|
||||
private $ids;
|
||||
private $ownerPHIDs;
|
||||
private $types;
|
||||
private $objectPHIDs;
|
||||
|
@ -15,6 +16,11 @@ final class PhabricatorFlagQuery
|
|||
private $needHandles;
|
||||
private $needObjects;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withOwnerPHIDs(array $owner_phids) {
|
||||
$this->ownerPHIDs = $owner_phids;
|
||||
return $this;
|
||||
|
@ -126,6 +132,13 @@ final class PhabricatorFlagQuery
|
|||
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
|
||||
$where = array();
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'flag.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->ownerPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
|
|
|
@ -24,26 +24,27 @@ final class HarbormasterBuildableActionController
|
|||
|
||||
$issuable = array();
|
||||
|
||||
foreach ($buildable->getBuilds() as $build) {
|
||||
$builds = $buildable->getBuilds();
|
||||
foreach ($builds as $key => $build) {
|
||||
switch ($action) {
|
||||
case HarbormasterBuildCommand::COMMAND_RESTART:
|
||||
if ($build->canRestartBuild()) {
|
||||
$issuable[] = $build;
|
||||
$issuable[$key] = $build;
|
||||
}
|
||||
break;
|
||||
case HarbormasterBuildCommand::COMMAND_PAUSE:
|
||||
if ($build->canPauseBuild()) {
|
||||
$issuable[] = $build;
|
||||
$issuable[$key] = $build;
|
||||
}
|
||||
break;
|
||||
case HarbormasterBuildCommand::COMMAND_RESUME:
|
||||
if ($build->canResumeBuild()) {
|
||||
$issuable[] = $build;
|
||||
$issuable[$key] = $build;
|
||||
}
|
||||
break;
|
||||
case HarbormasterBuildCommand::COMMAND_ABORT:
|
||||
if ($build->canAbortBuild()) {
|
||||
$issuable[] = $build;
|
||||
$issuable[$key] = $build;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -59,6 +60,14 @@ final class HarbormasterBuildableActionController
|
|||
}
|
||||
}
|
||||
|
||||
$building = false;
|
||||
foreach ($issuable as $key => $build) {
|
||||
if ($build->isBuilding()) {
|
||||
$building = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$return_uri = '/'.$buildable->getMonogram();
|
||||
if ($request->isDialogFormPost() && $issuable) {
|
||||
$editor = id(new HarbormasterBuildableTransactionEditor())
|
||||
|
@ -89,34 +98,137 @@ final class HarbormasterBuildableActionController
|
|||
return id(new AphrontRedirectResponse())->setURI($return_uri);
|
||||
}
|
||||
|
||||
$width = AphrontDialogView::WIDTH_DEFAULT;
|
||||
|
||||
switch ($action) {
|
||||
case HarbormasterBuildCommand::COMMAND_RESTART:
|
||||
// See T13348. The "Restart Builds" action may restart only a subset
|
||||
// of builds, so show the user a preview of which builds will actually
|
||||
// restart.
|
||||
|
||||
$body = array();
|
||||
|
||||
if ($issuable) {
|
||||
$title = pht('Really restart builds?');
|
||||
|
||||
if ($restricted) {
|
||||
$body = pht(
|
||||
'You only have permission to restart some builds. Progress '.
|
||||
'on builds you have permission to restart will be discarded '.
|
||||
'and they will restart. Side effects of these builds will '.
|
||||
'occur again. Really restart all builds?');
|
||||
} else {
|
||||
$body = pht(
|
||||
'Progress on all builds will be discarded, and all builds will '.
|
||||
'restart. Side effects of the builds will occur again. Really '.
|
||||
'restart all builds?');
|
||||
}
|
||||
|
||||
$title = pht('Restart Builds');
|
||||
$submit = pht('Restart Builds');
|
||||
} else {
|
||||
$title = pht('Unable to Restart Builds');
|
||||
}
|
||||
|
||||
if ($builds) {
|
||||
$width = AphrontDialogView::WIDTH_FORM;
|
||||
|
||||
$body[] = pht('Builds for this buildable:');
|
||||
|
||||
$rows = array();
|
||||
foreach ($builds as $key => $build) {
|
||||
if (isset($issuable[$key])) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-repeat green');
|
||||
$build_note = pht('Will Restart');
|
||||
} else {
|
||||
$icon = null;
|
||||
|
||||
try {
|
||||
$build->assertCanRestartBuild();
|
||||
} catch (HarbormasterRestartException $ex) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-times red');
|
||||
$build_note = pht(
|
||||
'%s: %s',
|
||||
phutil_tag('strong', array(), pht('Not Restartable')),
|
||||
$ex->getTitle());
|
||||
}
|
||||
|
||||
if (!$icon) {
|
||||
try {
|
||||
$build->assertCanIssueCommand($viewer, $action);
|
||||
} catch (PhabricatorPolicyException $ex) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-lock red');
|
||||
$build_note = pht(
|
||||
'%s: %s',
|
||||
phutil_tag('strong', array(), pht('Not Restartable')),
|
||||
pht('You do not have permission to restart this build.'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!$icon) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-times red');
|
||||
$build_note = pht('Will Not Restart');
|
||||
}
|
||||
}
|
||||
|
||||
$build_name = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $build->getURI(),
|
||||
'target' => '_blank',
|
||||
),
|
||||
pht('%s %s', $build->getObjectName(), $build->getName()));
|
||||
|
||||
$rows[] = array(
|
||||
$icon,
|
||||
$build_name,
|
||||
$build_note,
|
||||
);
|
||||
}
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
null,
|
||||
pht('Build'),
|
||||
pht('Action'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
'pri',
|
||||
'wide',
|
||||
));
|
||||
|
||||
$table = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'mlt mlb',
|
||||
),
|
||||
$table);
|
||||
|
||||
$body[] = $table;
|
||||
}
|
||||
|
||||
if ($issuable) {
|
||||
$warnings = array();
|
||||
|
||||
if ($restricted) {
|
||||
$body = pht('You do not have permission to restart any builds.');
|
||||
$warnings[] = pht(
|
||||
'You only have permission to restart some builds.');
|
||||
}
|
||||
|
||||
if ($building) {
|
||||
$warnings[] = pht(
|
||||
'Progress on running builds will be discarded.');
|
||||
}
|
||||
|
||||
$warnings[] = pht(
|
||||
'When a build is restarted, side effects associated with '.
|
||||
'the build may occur again.');
|
||||
|
||||
$body[] = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||
->setErrors($warnings);
|
||||
|
||||
$body[] = pht('Really restart builds?');
|
||||
} else {
|
||||
if ($restricted) {
|
||||
$body[] = pht('You do not have permission to restart any builds.');
|
||||
} else {
|
||||
$body = pht('No builds can be restarted.');
|
||||
$body[] = pht('No builds can be restarted.');
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case HarbormasterBuildCommand::COMMAND_PAUSE:
|
||||
if ($issuable) {
|
||||
|
@ -193,6 +305,7 @@ final class HarbormasterBuildableActionController
|
|||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($viewer)
|
||||
->setWidth($width)
|
||||
->setTitle($title)
|
||||
->appendChild($body)
|
||||
->addCancelButton($return_uri);
|
||||
|
|
|
@ -128,7 +128,7 @@ final class HarbormasterBuildableViewController
|
|||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-repeat')
|
||||
->setName(pht('Restart All Builds'))
|
||||
->setName(pht('Restart Builds'))
|
||||
->setHref($this->getApplicationURI($restart_uri))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_restart || !$can_edit));
|
||||
|
@ -136,7 +136,7 @@ final class HarbormasterBuildableViewController
|
|||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-pause')
|
||||
->setName(pht('Pause All Builds'))
|
||||
->setName(pht('Pause Builds'))
|
||||
->setHref($this->getApplicationURI($pause_uri))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_pause || !$can_edit));
|
||||
|
@ -144,7 +144,7 @@ final class HarbormasterBuildableViewController
|
|||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-play')
|
||||
->setName(pht('Resume All Builds'))
|
||||
->setName(pht('Resume Builds'))
|
||||
->setHref($this->getApplicationURI($resume_uri))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_resume || !$can_edit));
|
||||
|
@ -152,7 +152,7 @@ final class HarbormasterBuildableViewController
|
|||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-exclamation-triangle')
|
||||
->setName(pht('Abort All Builds'))
|
||||
->setName(pht('Abort Builds'))
|
||||
->setHref($this->getApplicationURI($abort_uri))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_abort || !$can_edit));
|
||||
|
|
|
@ -434,7 +434,7 @@ EODOCS
|
|||
$engine = id(new PhabricatorBoardResponseEngine())
|
||||
->setViewer($viewer)
|
||||
->setBoardPHID($board_phid)
|
||||
->setObjectPHID($object_phid)
|
||||
->setUpdatePHIDs(array($object_phid))
|
||||
->setVisiblePHIDs($visible_phids);
|
||||
|
||||
if ($ordering) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
final class ManiphestTransactionEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
private $oldProjectPHIDs;
|
||||
private $moreValidationErrors = array();
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
|
@ -378,6 +379,11 @@ final class ManiphestTransactionEditor
|
|||
}
|
||||
}
|
||||
|
||||
$send_notifications = PhabricatorNotificationClient::isEnabled();
|
||||
if ($send_notifications) {
|
||||
$this->oldProjectPHIDs = $this->loadProjectPHIDs($object);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
@ -859,4 +865,69 @@ final class ManiphestTransactionEditor
|
|||
return array_values($phid_list);
|
||||
}
|
||||
|
||||
protected function didApplyTransactions($object, array $xactions) {
|
||||
$send_notifications = PhabricatorNotificationClient::isEnabled();
|
||||
if ($send_notifications) {
|
||||
$old_phids = $this->oldProjectPHIDs;
|
||||
$new_phids = $this->loadProjectPHIDs($object);
|
||||
|
||||
// We want to emit update notifications for all old and new tagged
|
||||
// projects, and all parents of those projects. For example, if an
|
||||
// edit removes project "A > B" from a task, the "A" workboard should
|
||||
// receive an update event.
|
||||
|
||||
$project_phids = array_fuse($old_phids) + array_fuse($new_phids);
|
||||
$project_phids = array_keys($project_phids);
|
||||
|
||||
$projects = id(new PhabricatorProjectQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs($project_phids)
|
||||
->execute();
|
||||
|
||||
$notify_projects = array();
|
||||
foreach ($projects as $project) {
|
||||
$notify_projects[$project->getPHID()] = $project;
|
||||
foreach ($project->getAncestorProjects() as $ancestor) {
|
||||
$notify_projects[$ancestor->getPHID()] = $ancestor;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($notify_projects as $key => $project) {
|
||||
if (!$project->getHasWorkboard()) {
|
||||
unset($notify_projects[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$notify_phids = array_keys($notify_projects);
|
||||
|
||||
if ($notify_phids) {
|
||||
$data = array(
|
||||
'type' => 'workboards',
|
||||
'subscribers' => $notify_phids,
|
||||
);
|
||||
|
||||
PhabricatorNotificationClient::tryToPostMessage($data);
|
||||
}
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
private function loadProjectPHIDs(ManiphestTask $task) {
|
||||
if (!$task->getPHID()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$edge_query = id(new PhabricatorEdgeQuery())
|
||||
->withSourcePHIDs(array($task->getPHID()))
|
||||
->withEdgeTypes(
|
||||
array(
|
||||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
|
||||
));
|
||||
|
||||
$edge_query->execute();
|
||||
|
||||
return $edge_query->getDestinationPHIDs();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
final class PhabricatorMetaMTAErrorMailAction extends PhabricatorSystemAction {
|
||||
|
||||
public function getActionConstant() {
|
||||
return 'email.error';
|
||||
}
|
||||
const TYPECONST = 'email.error';
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 6 / phutil_units('1 hour in seconds');
|
||||
|
|
|
@ -37,4 +37,8 @@ final class PhabricatorNotificationClient extends Phobject {
|
|||
}
|
||||
}
|
||||
|
||||
public static function isEnabled() {
|
||||
return (bool)PhabricatorNotificationServerRef::getEnabledAdminServers();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,12 +15,11 @@ final class PhabricatorOAuthClientViewController
|
|||
}
|
||||
|
||||
$header = $this->buildHeaderView($client);
|
||||
$actions = $this->buildActionView($client);
|
||||
$properties = $this->buildPropertyListView($client);
|
||||
$properties->setActionList($actions);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb($client->getName());
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($client->getName())
|
||||
->setBorder(true);
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$client,
|
||||
|
@ -28,19 +27,27 @@ final class PhabricatorOAuthClientViewController
|
|||
$timeline->setShouldTerminate(true);
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->setHeaderText(pht('Details'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->addPropertyList($properties);
|
||||
|
||||
$title = pht('OAuth Application: %s', $client->getName());
|
||||
|
||||
return $this->newPage()
|
||||
->setCrumbs($crumbs)
|
||||
->setTitle($title)
|
||||
->appendChild(
|
||||
$curtain = $this->buildCurtain($client);
|
||||
|
||||
$columns = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setCurtain($curtain)
|
||||
->setMainColumn(
|
||||
array(
|
||||
$box,
|
||||
$timeline,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
->setCrumbs($crumbs)
|
||||
->setTitle($title)
|
||||
->appendChild($columns);
|
||||
}
|
||||
|
||||
private function buildHeaderView(PhabricatorOAuthServerClient $client) {
|
||||
|
@ -60,8 +67,9 @@ final class PhabricatorOAuthClientViewController
|
|||
return $header;
|
||||
}
|
||||
|
||||
private function buildActionView(PhabricatorOAuthServerClient $client) {
|
||||
private function buildCurtain(PhabricatorOAuthServerClient $client) {
|
||||
$viewer = $this->getViewer();
|
||||
$actions = array();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
|
@ -70,24 +78,19 @@ final class PhabricatorOAuthClientViewController
|
|||
|
||||
$id = $client->getID();
|
||||
|
||||
$view = id(new PhabricatorActionListView())
|
||||
->setUser($viewer);
|
||||
$actions[] = id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Application'))
|
||||
->setIcon('fa-pencil')
|
||||
->setWorkflow(!$can_edit)
|
||||
->setDisabled(!$can_edit)
|
||||
->setHref($client->getEditURI());
|
||||
|
||||
$view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Application'))
|
||||
->setIcon('fa-pencil')
|
||||
->setWorkflow(!$can_edit)
|
||||
->setDisabled(!$can_edit)
|
||||
->setHref($client->getEditURI()));
|
||||
|
||||
$view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Show Application Secret'))
|
||||
->setIcon('fa-eye')
|
||||
->setHref($this->getApplicationURI("client/secret/{$id}/"))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(true));
|
||||
$actions[] = id(new PhabricatorActionView())
|
||||
->setName(pht('Show Application Secret'))
|
||||
->setIcon('fa-eye')
|
||||
->setHref($this->getApplicationURI("client/secret/{$id}/"))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(true);
|
||||
|
||||
$is_disabled = $client->getIsDisabled();
|
||||
if ($is_disabled) {
|
||||
|
@ -100,22 +103,26 @@ final class PhabricatorOAuthClientViewController
|
|||
|
||||
$disable_uri = $this->getApplicationURI("client/disable/{$id}/");
|
||||
|
||||
$view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName($disable_text)
|
||||
->setIcon($disable_icon)
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_edit)
|
||||
->setHref($disable_uri));
|
||||
$actions[] = id(new PhabricatorActionView())
|
||||
->setName($disable_text)
|
||||
->setIcon($disable_icon)
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_edit)
|
||||
->setHref($disable_uri);
|
||||
|
||||
$view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Generate Test Token'))
|
||||
->setIcon('fa-plus')
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI("client/test/{$id}/")));
|
||||
$actions[] = id(new PhabricatorActionView())
|
||||
->setName(pht('Generate Test Token'))
|
||||
->setIcon('fa-plus')
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI("client/test/{$id}/"));
|
||||
|
||||
return $view;
|
||||
$curtain = $this->newCurtainView($client);
|
||||
|
||||
foreach ($actions as $action) {
|
||||
$curtain->addAction($action);
|
||||
}
|
||||
|
||||
return $curtain;
|
||||
}
|
||||
|
||||
private function buildPropertyListView(PhabricatorOAuthServerClient $client) {
|
||||
|
@ -132,10 +139,6 @@ final class PhabricatorOAuthClientViewController
|
|||
pht('Redirect URI'),
|
||||
$client->getRedirectURI());
|
||||
|
||||
$view->addProperty(
|
||||
pht('Created'),
|
||||
phabricator_datetime($client->getDateCreated(), $viewer));
|
||||
|
||||
return $view;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,9 @@ final class PhabricatorOAuthServerClientPHIDType extends PhabricatorPHIDType {
|
|||
foreach ($handles as $phid => $handle) {
|
||||
$client = $objects[$phid];
|
||||
|
||||
$handle->setName($client->getName());
|
||||
$handle
|
||||
->setName($client->getName())
|
||||
->setURI($client->getURI());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,12 @@ final class PhabricatorOAuthServerClient
|
|||
PhabricatorOAuthServerClientPHIDType::TYPECONST);
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return urisprintf(
|
||||
'/oauthserver/client/view/%d/',
|
||||
$this->getID());
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
abstract class PhabricatorPasteDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'pastebin';
|
||||
return 'paste';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ final class PhabricatorPasteTransaction
|
|||
const MAILTAG_COMMENT = 'paste-comment';
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'pastebin';
|
||||
return 'paste';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
|
|
|
@ -44,6 +44,7 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
|
|||
$this->getQueryRoutePattern() => 'PhabricatorPeopleListController',
|
||||
'logs/' => array(
|
||||
$this->getQueryRoutePattern() => 'PhabricatorPeopleLogsController',
|
||||
'(?P<id>\d+)/' => 'PhabricatorPeopleLogViewController',
|
||||
),
|
||||
'invite/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?'
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleLogViewController
|
||||
extends PhabricatorPeopleController {
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
$log = id(new PhabricatorPeopleLogQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$log) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$logs_uri = $this->getApplicationURI('logs/');
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Activity Logs'), $logs_uri)
|
||||
->addTextCrumb($log->getObjectName())
|
||||
->setBorder(true);
|
||||
|
||||
$header = $this->buildHeaderView($log);
|
||||
$properties = $this->buildPropertiesView($log);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->addPropertySection(pht('Details'), $properties);
|
||||
|
||||
return $this->newPage()
|
||||
->setCrumbs($crumbs)
|
||||
->setTitle($log->getObjectName())
|
||||
->appendChild($view);
|
||||
}
|
||||
|
||||
private function buildHeaderView(PhabricatorUserLog $log) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$view = id(new PHUIHeaderView())
|
||||
->setViewer($viewer)
|
||||
->setHeader($log->getObjectName());
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
private function buildPropertiesView(PhabricatorUserLog $log) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setViewer($viewer);
|
||||
|
||||
$type_map = PhabricatorUserLogType::getAllLogTypes();
|
||||
$type_map = mpull($type_map, 'getLogTypeName', 'getLogTypeKey');
|
||||
|
||||
$action = $log->getAction();
|
||||
$type_name = idx($type_map, $action, $action);
|
||||
|
||||
$view->addProperty(pht('Event Type'), $type_name);
|
||||
|
||||
$view->addProperty(
|
||||
pht('Event Date'),
|
||||
phabricator_datetime($log->getDateCreated(), $viewer));
|
||||
|
||||
$actor_phid = $log->getActorPHID();
|
||||
if ($actor_phid) {
|
||||
$view->addProperty(
|
||||
pht('Acting User'),
|
||||
$viewer->renderHandle($actor_phid));
|
||||
}
|
||||
|
||||
$user_phid = $log->getUserPHID();
|
||||
if ($user_phid) {
|
||||
$view->addProperty(
|
||||
pht('Affected User'),
|
||||
$viewer->renderHandle($user_phid));
|
||||
}
|
||||
|
||||
$remote_address = $log->getRemoteAddressForViewer($viewer);
|
||||
if ($remote_address !== null) {
|
||||
$view->addProperty(pht('Remote Address'), $remote_address);
|
||||
}
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
}
|
|
@ -252,15 +252,30 @@ final class PhabricatorPeopleProfileViewController
|
|||
PhabricatorUser $user,
|
||||
$viewer) {
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$query->withFilterPHIDs(
|
||||
array(
|
||||
$user->getPHID(),
|
||||
));
|
||||
$query->setLimit(100);
|
||||
$query->setViewer($viewer);
|
||||
$query = id(new PhabricatorFeedQuery())
|
||||
->setViewer($viewer)
|
||||
->withFilterPHIDs(array($user->getPHID()))
|
||||
->setLimit(100)
|
||||
->setReturnPartialResultsOnOverheat(true);
|
||||
|
||||
$stories = $query->execute();
|
||||
|
||||
$overheated_view = null;
|
||||
$is_overheated = $query->getIsOverheated();
|
||||
if ($is_overheated) {
|
||||
$overheated_message =
|
||||
PhabricatorApplicationSearchController::newOverheatedError(
|
||||
(bool)$stories);
|
||||
|
||||
$overheated_view = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||
->setTitle(pht('Query Overheated'))
|
||||
->setErrors(
|
||||
array(
|
||||
$overheated_message,
|
||||
));
|
||||
}
|
||||
|
||||
$builder = new PhabricatorFeedBuilder($stories);
|
||||
$builder->setUser($viewer);
|
||||
$builder->setShowHovercards(true);
|
||||
|
@ -268,8 +283,10 @@ final class PhabricatorPeopleProfileViewController
|
|||
'requires but just a single step.'));
|
||||
$view = $builder->buildView();
|
||||
|
||||
return $view->render();
|
||||
|
||||
return array(
|
||||
$overheated_view,
|
||||
$view->render(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,18 +74,11 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
throw $ex;
|
||||
}
|
||||
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$this->requireActor(),
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_CREATE);
|
||||
$log->setNewValue($email->getAddress());
|
||||
$log->save();
|
||||
|
||||
if ($is_reassign) {
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$this->requireActor(),
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EMAIL_REASSIGN);
|
||||
PhabricatorReassignEmailUserLogType::LOGTYPE);
|
||||
$log->setNewValue($email->getAddress());
|
||||
$log->save();
|
||||
}
|
||||
|
@ -100,35 +93,6 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task edit
|
||||
*/
|
||||
public function updateUser(
|
||||
PhabricatorUser $user,
|
||||
PhabricatorUserEmail $email = null) {
|
||||
|
||||
if (!$user->getID()) {
|
||||
throw new Exception(pht('User has not been created yet!'));
|
||||
}
|
||||
|
||||
$user->openTransaction();
|
||||
$user->save();
|
||||
if ($email) {
|
||||
$email->save();
|
||||
}
|
||||
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$this->requireActor(),
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EDIT);
|
||||
$log->save();
|
||||
|
||||
$user->saveTransaction();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/* -( Editing Roles )------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
|
@ -151,18 +115,9 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
return $this;
|
||||
}
|
||||
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_SYSTEM_AGENT);
|
||||
$log->setOldValue($user->getIsSystemAgent());
|
||||
$log->setNewValue($system_agent);
|
||||
|
||||
$user->setIsSystemAgent((int)$system_agent);
|
||||
$user->save();
|
||||
|
||||
$log->save();
|
||||
|
||||
$user->endWriteLocking();
|
||||
$user->saveTransaction();
|
||||
|
||||
|
@ -189,18 +144,9 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
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();
|
||||
|
||||
|
@ -249,7 +195,7 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EMAIL_ADD);
|
||||
PhabricatorAddEmailUserLogType::LOGTYPE);
|
||||
$log->setNewValue($email->getAddress());
|
||||
$log->save();
|
||||
|
||||
|
@ -300,7 +246,7 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EMAIL_REMOVE);
|
||||
PhabricatorRemoveEmailUserLogType::LOGTYPE);
|
||||
$log->setOldValue($email->getAddress());
|
||||
$log->save();
|
||||
|
||||
|
@ -366,7 +312,7 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EMAIL_PRIMARY);
|
||||
PhabricatorPrimaryEmailUserLogType::LOGTYPE);
|
||||
$log->setOldValue($old_primary ? $old_primary->getAddress() : null);
|
||||
$log->setNewValue($email->getAddress());
|
||||
|
||||
|
@ -425,7 +371,7 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EMAIL_VERIFY);
|
||||
PhabricatorVerifyEmailUserLogType::LOGTYPE);
|
||||
$log->setNewValue($email->getAddress());
|
||||
$log->save();
|
||||
}
|
||||
|
@ -487,7 +433,7 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EMAIL_REASSIGN);
|
||||
PhabricatorReassignEmailUserLogType::LOGTYPE);
|
||||
$log->setNewValue($email->getAddress());
|
||||
$log->save();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleEmailLoginMailEngine
|
||||
extends PhabricatorPeopleMailEngine {
|
||||
|
||||
public function validateMail() {
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
if ($recipient->getIsDisabled()) {
|
||||
$this->throwValidationException(
|
||||
pht('User is Disabled'),
|
||||
pht(
|
||||
'You can not send an email login link to this email address '.
|
||||
'because the associated user account is disabled.'));
|
||||
}
|
||||
|
||||
if (!$recipient->canEstablishWebSessions()) {
|
||||
$this->throwValidationException(
|
||||
pht('Not a Normal User'),
|
||||
pht(
|
||||
'You can not send an email login link to this email address '.
|
||||
'because the associated user account is not a normal user account '.
|
||||
'and can not log in to the web interface.'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function newMail() {
|
||||
$is_set_password = $this->isSetPasswordWorkflow();
|
||||
|
||||
if ($is_set_password) {
|
||||
$subject = pht('[Phabricator] Account Password Link');
|
||||
} else {
|
||||
$subject = pht('[Phabricator] Account Login Link');
|
||||
}
|
||||
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
PhabricatorSystemActionEngine::willTakeAction(
|
||||
array($recipient->getPHID()),
|
||||
new PhabricatorAuthEmailLoginAction(),
|
||||
1);
|
||||
|
||||
$engine = new PhabricatorAuthSessionEngine();
|
||||
$login_uri = $engine->getOneTimeLoginURI(
|
||||
$recipient,
|
||||
null,
|
||||
PhabricatorAuthSessionEngine::ONETIME_RESET);
|
||||
|
||||
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||
$have_passwords = $this->isPasswordAuthEnabled();
|
||||
|
||||
$body = array();
|
||||
|
||||
if ($is_set_password) {
|
||||
$message_key = PhabricatorAuthEmailSetPasswordMessageType::MESSAGEKEY;
|
||||
} else {
|
||||
$message_key = PhabricatorAuthEmailLoginMessageType::MESSAGEKEY;
|
||||
}
|
||||
|
||||
$message_body = PhabricatorAuthMessage::loadMessageText(
|
||||
$recipient,
|
||||
$message_key);
|
||||
if (strlen($message_body)) {
|
||||
$body[] = $this->newRemarkupText($message_body);
|
||||
}
|
||||
|
||||
if ($have_passwords) {
|
||||
if ($is_set_password) {
|
||||
$body[] = pht(
|
||||
'You can use this link to set a password on your account:'.
|
||||
"\n\n %s\n",
|
||||
$login_uri);
|
||||
} else if ($is_serious) {
|
||||
$body[] = pht(
|
||||
"You can use this link to reset your Phabricator password:".
|
||||
"\n\n %s\n",
|
||||
$login_uri);
|
||||
} else {
|
||||
$body[] = pht(
|
||||
"Condolences on forgetting your password. You can use this ".
|
||||
"link to reset it:\n\n".
|
||||
" %s\n\n".
|
||||
"After you set a new password, consider writing it down on a ".
|
||||
"sticky note and attaching it to your monitor so you don't ".
|
||||
"forget again! Choosing a very short, easy-to-remember password ".
|
||||
"like \"cat\" or \"1234\" might also help.\n\n".
|
||||
"Best Wishes,\nPhabricator\n",
|
||||
$login_uri);
|
||||
|
||||
}
|
||||
} else {
|
||||
$body[] = pht(
|
||||
"You can use this login link to regain access to your Phabricator ".
|
||||
"account:".
|
||||
"\n\n".
|
||||
" %s\n",
|
||||
$login_uri);
|
||||
}
|
||||
|
||||
$body = implode("\n\n", $body);
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->setBody($body);
|
||||
}
|
||||
|
||||
private function isPasswordAuthEnabled() {
|
||||
return (bool)PhabricatorPasswordAuthProvider::getPasswordProvider();
|
||||
}
|
||||
|
||||
private function isSetPasswordWorkflow() {
|
||||
$sender = $this->getSender();
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
// Users can hit the "login with an email link" workflow while trying to
|
||||
// set a password on an account which does not yet have a password. We
|
||||
// require they verify that they own the email address and send them
|
||||
// through the email login flow. In this case, the messaging is slightly
|
||||
// different.
|
||||
|
||||
if ($sender->getPHID()) {
|
||||
if ($sender->getPHID() === $recipient->getPHID()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,8 @@ abstract class PhabricatorPeopleMailEngine
|
|||
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $recipientAddress;
|
||||
private $activityLog;
|
||||
|
||||
final public function setSender(PhabricatorUser $sender) {
|
||||
$this->sender = $sender;
|
||||
|
@ -30,6 +32,31 @@ abstract class PhabricatorPeopleMailEngine
|
|||
return $this->recipient;
|
||||
}
|
||||
|
||||
final public function setRecipientAddress(PhutilEmailAddress $address) {
|
||||
$this->recipientAddress = $address;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getRecipientAddress() {
|
||||
if (!$this->recipientAddress) {
|
||||
throw new PhutilInvalidStateException('recipientAddress');
|
||||
}
|
||||
return $this->recipientAddress;
|
||||
}
|
||||
|
||||
final public function hasRecipientAddress() {
|
||||
return ($this->recipientAddress !== null);
|
||||
}
|
||||
|
||||
final public function setActivityLog(PhabricatorUserLog $activity_log) {
|
||||
$this->activityLog = $activity_log;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getActivityLog() {
|
||||
return $this->activityLog;
|
||||
}
|
||||
|
||||
final public function canSendMail() {
|
||||
try {
|
||||
$this->validateMail();
|
||||
|
@ -43,6 +70,26 @@ abstract class PhabricatorPeopleMailEngine
|
|||
$this->validateMail();
|
||||
$mail = $this->newMail();
|
||||
|
||||
if ($this->hasRecipientAddress()) {
|
||||
$recipient_address = $this->getRecipientAddress();
|
||||
$mail->addRawTos(array($recipient_address->getAddress()));
|
||||
} else {
|
||||
$recipient = $this->getRecipient();
|
||||
$mail->addTos(array($recipient->getPHID()));
|
||||
}
|
||||
|
||||
$activity_log = $this->getActivityLog();
|
||||
if ($activity_log) {
|
||||
$activity_log->save();
|
||||
|
||||
$body = array();
|
||||
$body[] = rtrim($mail->getBody(), "\n");
|
||||
$body[] = pht('Activity Log ID: #%d', $activity_log->getID());
|
||||
$body = implode("\n\n", $body)."\n";
|
||||
|
||||
$mail->setBody($body);
|
||||
}
|
||||
|
||||
$mail
|
||||
->setForceDelivery(true)
|
||||
->save();
|
||||
|
@ -53,7 +100,6 @@ abstract class PhabricatorPeopleMailEngine
|
|||
abstract public function validateMail();
|
||||
abstract protected function newMail();
|
||||
|
||||
|
||||
final protected function throwValidationException($title, $body) {
|
||||
throw new PhabricatorPeopleMailEngineException($title, $body);
|
||||
}
|
||||
|
@ -66,7 +112,10 @@ abstract class PhabricatorPeopleMailEngine
|
|||
->setConfig('uri.base', PhabricatorEnv::getProductionURI('/'))
|
||||
->setMode(PhutilRemarkupEngine::MODE_TEXT);
|
||||
|
||||
return $engine->markupText($text);
|
||||
$rendered_text = $engine->markupText($text);
|
||||
$rendered_text = rtrim($rendered_text, "\n");
|
||||
|
||||
return $rendered_text;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ final class PhabricatorPeopleUsernameMailEngine
|
|||
|
||||
protected function newMail() {
|
||||
$sender = $this->getSender();
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
$sender_username = $sender->getUsername();
|
||||
$sender_realname = $sender->getRealName();
|
||||
|
@ -52,7 +51,6 @@ final class PhabricatorPeopleUsernameMailEngine
|
|||
$new_username));
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->addTos(array($recipient->getPHID()))
|
||||
->setSubject(pht('[Phabricator] Username Changed'))
|
||||
->setBody($body);
|
||||
}
|
||||
|
|
|
@ -104,7 +104,6 @@ final class PhabricatorPeopleWelcomeMailEngine
|
|||
$message = implode("\n\n", $message);
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->addTos(array($recipient->getPHID()))
|
||||
->setSubject(pht('[Phabricator] Welcome to Phabricator'))
|
||||
->setBody($message);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
final class PhabricatorPeopleLogQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $actorPHIDs;
|
||||
private $userPHIDs;
|
||||
private $relatedPHIDs;
|
||||
|
@ -12,6 +13,11 @@ final class PhabricatorPeopleLogQuery
|
|||
private $dateCreatedMin;
|
||||
private $dateCreatedMax;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withActorPHIDs(array $actor_phids) {
|
||||
$this->actorPHIDs = $actor_phids;
|
||||
return $this;
|
||||
|
@ -59,6 +65,13 @@ final class PhabricatorPeopleLogQuery
|
|||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->actorPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
|
|
|
@ -64,6 +64,9 @@ final class PhabricatorPeopleLogSearchEngine
|
|||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
$types = PhabricatorUserLogType::getAllLogTypes();
|
||||
$types = mpull($types, 'getLogTypeName', 'getLogTypeKey');
|
||||
|
||||
return array(
|
||||
id(new PhabricatorUsersSearchField())
|
||||
->setKey('userPHIDs')
|
||||
|
@ -75,11 +78,11 @@ final class PhabricatorPeopleLogSearchEngine
|
|||
->setAliases(array('actors', 'actor', 'actorPHID'))
|
||||
->setLabel(pht('Actors'))
|
||||
->setDescription(pht('Search for activity by specific users.')),
|
||||
id(new PhabricatorSearchCheckboxesField())
|
||||
id(new PhabricatorSearchDatasourceField())
|
||||
->setKey('actions')
|
||||
->setLabel(pht('Actions'))
|
||||
->setDescription(pht('Search for particular types of activity.'))
|
||||
->setOptions(PhabricatorUserLog::getActionTypeMap()),
|
||||
->setDatasource(new PhabricatorUserLogTypeDatasource()),
|
||||
id(new PhabricatorSearchTextField())
|
||||
->setKey('ip')
|
||||
->setLabel(pht('Filter IP'))
|
||||
|
@ -194,7 +197,8 @@ final class PhabricatorPeopleLogSearchEngine
|
|||
}
|
||||
$handles = $viewer->loadHandles($phids);
|
||||
|
||||
$action_map = PhabricatorUserLog::getActionTypeMap();
|
||||
$types = PhabricatorUserLogType::getAllLogTypes();
|
||||
$types = mpull($types, 'getLogTypeName', 'getLogTypeKey');
|
||||
|
||||
$export = array();
|
||||
foreach ($logs as $log) {
|
||||
|
@ -214,7 +218,7 @@ final class PhabricatorPeopleLogSearchEngine
|
|||
}
|
||||
|
||||
$action = $log->getAction();
|
||||
$action_name = idx($action_map, $action, pht('Unknown ("%s")', $action));
|
||||
$action_name = idx($types, $action, pht('Unknown ("%s")', $action));
|
||||
|
||||
$map = array(
|
||||
'actorPHID' => $actor_phid,
|
||||
|
|
|
@ -3,43 +3,6 @@
|
|||
final class PhabricatorUserLog extends PhabricatorUserDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
const ACTION_LOGIN = 'login';
|
||||
const ACTION_LOGIN_PARTIAL = 'login-partial';
|
||||
const ACTION_LOGIN_FULL = 'login-full';
|
||||
const ACTION_LOGOUT = 'logout';
|
||||
const ACTION_LOGIN_FAILURE = 'login-fail';
|
||||
const ACTION_LOGIN_LEGALPAD = 'login-legalpad';
|
||||
const ACTION_RESET_PASSWORD = 'reset-pass';
|
||||
|
||||
const ACTION_CREATE = 'create';
|
||||
const ACTION_EDIT = 'edit';
|
||||
|
||||
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';
|
||||
|
||||
const ACTION_CONDUIT_CERTIFICATE = 'conduit-cert';
|
||||
const ACTION_CONDUIT_CERTIFICATE_FAILURE = 'conduit-cert-fail';
|
||||
|
||||
const ACTION_EMAIL_PRIMARY = 'email-primary';
|
||||
const ACTION_EMAIL_REMOVE = 'email-remove';
|
||||
const ACTION_EMAIL_ADD = 'email-add';
|
||||
const ACTION_EMAIL_VERIFY = 'email-verify';
|
||||
const ACTION_EMAIL_REASSIGN = 'email-reassign';
|
||||
|
||||
const ACTION_CHANGE_PASSWORD = 'change-password';
|
||||
const ACTION_CHANGE_USERNAME = 'change-username';
|
||||
|
||||
const ACTION_ENTER_HISEC = 'hisec-enter';
|
||||
const ACTION_EXIT_HISEC = 'hisec-exit';
|
||||
const ACTION_FAIL_HISEC = 'hisec-fail';
|
||||
|
||||
const ACTION_MULTI_ADD = 'multi-add';
|
||||
const ACTION_MULTI_REMOVE = 'multi-remove';
|
||||
|
||||
protected $actorPHID;
|
||||
protected $userPHID;
|
||||
protected $action;
|
||||
|
@ -49,44 +12,6 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
|||
protected $remoteAddr;
|
||||
protected $session;
|
||||
|
||||
public static function getActionTypeMap() {
|
||||
return array(
|
||||
self::ACTION_LOGIN => pht('Login'),
|
||||
self::ACTION_LOGIN_PARTIAL => pht('Login: Partial Login'),
|
||||
self::ACTION_LOGIN_FULL => pht('Login: Upgrade to Full'),
|
||||
self::ACTION_LOGIN_FAILURE => pht('Login: Failure'),
|
||||
self::ACTION_LOGIN_LEGALPAD =>
|
||||
pht('Login: Signed Required Legalpad Documents'),
|
||||
self::ACTION_LOGOUT => pht('Logout'),
|
||||
self::ACTION_RESET_PASSWORD => pht('Reset Password'),
|
||||
self::ACTION_CREATE => pht('Create Account'),
|
||||
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'),
|
||||
self::ACTION_CONDUIT_CERTIFICATE
|
||||
=> pht('Conduit: Read Certificate'),
|
||||
self::ACTION_CONDUIT_CERTIFICATE_FAILURE
|
||||
=> pht('Conduit: Read Certificate Failure'),
|
||||
self::ACTION_EMAIL_PRIMARY => pht('Email: Change Primary'),
|
||||
self::ACTION_EMAIL_ADD => pht('Email: Add Address'),
|
||||
self::ACTION_EMAIL_REMOVE => pht('Email: Remove Address'),
|
||||
self::ACTION_EMAIL_VERIFY => pht('Email: Verify'),
|
||||
self::ACTION_EMAIL_REASSIGN => pht('Email: Reassign'),
|
||||
self::ACTION_CHANGE_PASSWORD => pht('Change Password'),
|
||||
self::ACTION_CHANGE_USERNAME => pht('Change Username'),
|
||||
self::ACTION_ENTER_HISEC => pht('Hisec: Enter'),
|
||||
self::ACTION_EXIT_HISEC => pht('Hisec: Exit'),
|
||||
self::ACTION_FAIL_HISEC => pht('Hisec: Failed Attempt'),
|
||||
self::ACTION_MULTI_ADD => pht('Multi-Factor: Add Factor'),
|
||||
self::ACTION_MULTI_REMOVE => pht('Multi-Factor: Remove Factor'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function initializeNewLog(
|
||||
PhabricatorUser $actor = null,
|
||||
$object_phid = null,
|
||||
|
@ -175,6 +100,43 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
|||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return urisprintf('/people/logs/%s/', $this->getID());
|
||||
}
|
||||
|
||||
public function getObjectName() {
|
||||
return pht('Activity Log %d', $this->getID());
|
||||
}
|
||||
|
||||
public function getRemoteAddressForViewer(PhabricatorUser $viewer) {
|
||||
$viewer_phid = $viewer->getPHID();
|
||||
$actor_phid = $this->getActorPHID();
|
||||
$user_phid = $this->getUserPHID();
|
||||
|
||||
if (!$viewer_phid) {
|
||||
$can_see_ip = false;
|
||||
} else if ($viewer->getIsAdmin()) {
|
||||
$can_see_ip = true;
|
||||
} else if ($viewer_phid == $actor_phid) {
|
||||
// You can see the address if you took the action.
|
||||
$can_see_ip = true;
|
||||
} else if (!$actor_phid && ($viewer_phid == $user_phid)) {
|
||||
// You can see the address if it wasn't authenticated and applied
|
||||
// to you (partial login).
|
||||
$can_see_ip = true;
|
||||
} else {
|
||||
// You can't see the address when an administrator disables your
|
||||
// account, since it's their address.
|
||||
$can_see_ip = false;
|
||||
}
|
||||
|
||||
if (!$can_see_ip) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getRemoteAddr();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorUserLogTypeDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function getBrowseTitle() {
|
||||
return pht('Browse Log Types');
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a log type name...');
|
||||
}
|
||||
|
||||
public function getDatasourceApplicationClass() {
|
||||
return 'PhabricatorPeopleApplication';
|
||||
}
|
||||
|
||||
public function loadResults() {
|
||||
$results = $this->buildResults();
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
|
||||
protected function renderSpecialTokens(array $values) {
|
||||
return $this->renderTokensFromResults($this->buildResults(), $values);
|
||||
}
|
||||
|
||||
private function buildResults() {
|
||||
$results = array();
|
||||
|
||||
$type_map = PhabricatorUserLogType::getAllLogTypes();
|
||||
foreach ($type_map as $type_key => $type) {
|
||||
|
||||
$result = id(new PhabricatorTypeaheadResult())
|
||||
->setPHID($type_key)
|
||||
->setName($type->getLogTypeName());
|
||||
|
||||
$results[$type_key] = $result;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAddEmailUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'email-add';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Email: Add Address');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAddMultifactorUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'multi-add';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Multi-Factor: Add Factor');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorChangePasswordUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'change-password';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Change Password');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConduitCertificateFailureUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'conduit-cert-fail';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Conduit: Read Certificate Failure');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConduitCertificateUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'conduit-cert';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Conduit: Read Certificate');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorEmailLoginUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'email-login';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Email: Recovery Link');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorEnterHisecUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'hisec-enter';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Hisec: Enter');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorExitHisecUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'hisec-exit';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Hisec: Exit');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorFailHisecUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'hisec-fail';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Hisec: Failed Attempt');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorFullLoginUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'login-full';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Login: Upgrade to Full');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorLoginFailureUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'login-fail';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Login: Failure');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorLoginUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'login';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Login');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorLogoutUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'logout';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Logout');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPartialLoginUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'login-partial';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Login: Partial Login');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPrimaryEmailUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'email-primary';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Email: Change Primary');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorReassignEmailUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'email-reassign';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Email: Reassign');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRemoveEmailUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'email-remove';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Email: Remove Address');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRemoveMultifactorUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'multi-remove';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Multi-Factor: Remove Factor');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorResetPasswordUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'reset-pass';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Reset Password');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorSignDocumentsUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'login-legalpad';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Login: Signed Required Legalpad Documents');
|
||||
}
|
||||
|
||||
}
|
19
src/applications/people/userlog/PhabricatorUserLogType.php
Normal file
19
src/applications/people/userlog/PhabricatorUserLogType.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorUserLogType
|
||||
extends Phobject {
|
||||
|
||||
final public function getLogTypeKey() {
|
||||
return $this->getPhobjectClassConstant('LOGTYPE', 32);
|
||||
}
|
||||
|
||||
abstract public function getLogTypeName();
|
||||
|
||||
final public static function getAllLogTypes() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getLogTypeKey')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorVerifyEmailUserLogType
|
||||
extends PhabricatorUserLogType {
|
||||
|
||||
const LOGTYPE = 'email-verify';
|
||||
|
||||
public function getLogTypeName() {
|
||||
return pht('Email: Verify Address');
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,9 @@ final class PhabricatorUserLogView extends AphrontView {
|
|||
}
|
||||
$handles = $viewer->loadHandles($phids);
|
||||
|
||||
$action_map = PhabricatorUserLog::getActionTypeMap();
|
||||
$types = PhabricatorUserLogType::getAllLogTypes();
|
||||
$types = mpull($types, 'getLogTypeName', 'getLogTypeKey');
|
||||
|
||||
$base_uri = $this->searchBaseURI;
|
||||
|
||||
$viewer_phid = $viewer->getPHID();
|
||||
|
@ -39,37 +41,20 @@ final class PhabricatorUserLogView extends AphrontView {
|
|||
$actor_phid = $log->getActorPHID();
|
||||
$user_phid = $log->getUserPHID();
|
||||
|
||||
if ($viewer->getIsAdmin()) {
|
||||
$can_see_ip = true;
|
||||
} else if ($viewer_phid == $actor_phid) {
|
||||
// You can see the address if you took the action.
|
||||
$can_see_ip = true;
|
||||
} else if (!$actor_phid && ($viewer_phid == $user_phid)) {
|
||||
// You can see the address if it wasn't authenticated and applied
|
||||
// to you (partial login).
|
||||
$can_see_ip = true;
|
||||
} else {
|
||||
// You can't see the address when an administrator disables your
|
||||
// account, since it's their address.
|
||||
$can_see_ip = false;
|
||||
}
|
||||
|
||||
if ($can_see_ip) {
|
||||
$ip = $log->getRemoteAddr();
|
||||
$remote_address = $log->getRemoteAddressForViewer($viewer);
|
||||
if ($remote_address !== null) {
|
||||
if ($base_uri) {
|
||||
$ip = phutil_tag(
|
||||
$remote_address = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $base_uri.'?ip='.$ip.'#R',
|
||||
'href' => $base_uri.'?ip='.$remote_address.'#R',
|
||||
),
|
||||
$ip);
|
||||
$remote_address);
|
||||
}
|
||||
} else {
|
||||
$ip = null;
|
||||
}
|
||||
|
||||
$action = $log->getAction();
|
||||
$action_name = idx($action_map, $action, $action);
|
||||
$action_name = idx($types, $action, $action);
|
||||
|
||||
if ($actor_phid) {
|
||||
$actor_name = $handles[$actor_phid]->renderLink();
|
||||
|
@ -83,37 +68,47 @@ final class PhabricatorUserLogView extends AphrontView {
|
|||
$user_name = null;
|
||||
}
|
||||
|
||||
$action_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $log->getURI(),
|
||||
),
|
||||
$action_name);
|
||||
|
||||
$rows[] = array(
|
||||
phabricator_date($log->getDateCreated(), $viewer),
|
||||
phabricator_time($log->getDateCreated(), $viewer),
|
||||
$action_name,
|
||||
$log->getID(),
|
||||
$action_link,
|
||||
$actor_name,
|
||||
$user_name,
|
||||
$ip,
|
||||
$remote_address,
|
||||
$session,
|
||||
phabricator_date($log->getDateCreated(), $viewer),
|
||||
phabricator_time($log->getDateCreated(), $viewer),
|
||||
);
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
pht('Date'),
|
||||
pht('Time'),
|
||||
pht('ID'),
|
||||
pht('Action'),
|
||||
pht('Actor'),
|
||||
pht('User'),
|
||||
pht('IP'),
|
||||
pht('Session'),
|
||||
pht('Date'),
|
||||
pht('Time'),
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'right',
|
||||
'wide',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'n',
|
||||
'',
|
||||
'right',
|
||||
));
|
||||
|
||||
return $table;
|
||||
|
|
|
@ -19,10 +19,6 @@ final class PhabricatorUserApproveTransaction
|
|||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$user = $object;
|
||||
$this->newUserLog(PhabricatorUserLog::ACTION_APPROVE)
|
||||
->setOldValue((bool)$user->getIsApproved())
|
||||
->setNewValue((bool)$value)
|
||||
->save();
|
||||
|
||||
$actor = $this->getActor();
|
||||
$title = pht(
|
||||
|
|
|
@ -17,13 +17,6 @@ final class PhabricatorUserDisableTransaction
|
|||
$object->setIsDisabled((int)$value);
|
||||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$this->newUserLog(PhabricatorUserLog::ACTION_DISABLE)
|
||||
->setOldValue((bool)$object->getIsDisabled())
|
||||
->setNewValue((bool)$value)
|
||||
->save();
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$new = $this->getNewValue();
|
||||
if ($new) {
|
||||
|
|
|
@ -17,15 +17,6 @@ final class PhabricatorUserEmpowerTransaction
|
|||
$object->setIsAdmin((int)$value);
|
||||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$user = $object;
|
||||
|
||||
$this->newUserLog(PhabricatorUserLog::ACTION_ADMIN)
|
||||
->setOldValue($this->getOldValue())
|
||||
->setNewValue($value)
|
||||
->save();
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$user = $object;
|
||||
$actor = $this->getActor();
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorUserTransactionType
|
||||
extends PhabricatorModularTransactionType {
|
||||
|
||||
protected function newUserLog($action) {
|
||||
return PhabricatorUserLog::initializeNewLog(
|
||||
$this->getActor(),
|
||||
$this->getObject()->getPHID(),
|
||||
$action);
|
||||
}
|
||||
|
||||
}
|
||||
extends PhabricatorModularTransactionType {}
|
||||
|
|
|
@ -24,11 +24,6 @@ final class PhabricatorUserUsernameTransaction
|
|||
$old_username = $this->getOldValue();
|
||||
$new_username = $this->getNewValue();
|
||||
|
||||
$this->newUserLog(PhabricatorUserLog::ACTION_CHANGE_USERNAME)
|
||||
->setOldValue($old_username)
|
||||
->setNewValue($new_username)
|
||||
->save();
|
||||
|
||||
// The SSH key cache currently includes usernames, so dirty it. See T12554
|
||||
// for discussion.
|
||||
PhabricatorAuthSSHKeyQuery::deleteSSHKeyCache();
|
||||
|
|
|
@ -93,10 +93,6 @@ abstract class PhameLiveController extends PhameController {
|
|||
->needHeaderImage(true)
|
||||
->withIDs(array($post_id));
|
||||
|
||||
if ($blog) {
|
||||
$post_query->withBlogPHIDs(array($blog->getPHID()));
|
||||
}
|
||||
|
||||
// Only show published posts on external domains.
|
||||
if ($is_external) {
|
||||
$post_query->withVisibility(
|
||||
|
@ -123,10 +119,15 @@ abstract class PhameLiveController extends PhameController {
|
|||
$this->post = $post;
|
||||
|
||||
// If we have a post, canonicalize the URI to the post's current slug and
|
||||
// redirect the user if it isn't correct.
|
||||
// redirect the user if it isn't correct. Likewise, canonicalize the URI
|
||||
// if the blog ID is wrong. See T13353.
|
||||
if ($post) {
|
||||
$slug = $request->getURIData('slug');
|
||||
if ($post->getSlug() != $slug) {
|
||||
|
||||
$wrong_slug = ($post->getSlug() !== $slug);
|
||||
$wrong_blog = ($post->getBlog()->getID() !== $blog->getID());
|
||||
|
||||
if ($wrong_slug || $wrong_blog) {
|
||||
if ($is_live) {
|
||||
if ($is_external) {
|
||||
$uri = $post->getExternalLiveURI();
|
||||
|
|
|
@ -103,7 +103,7 @@ final class PholioMockImagesView extends AphrontView {
|
|||
'width' => $x,
|
||||
'height' => $y,
|
||||
'title' => $image->getName(),
|
||||
'descriptionMarkup' => $description,
|
||||
'descriptionMarkup' => hsprintf('%s', $description),
|
||||
'isObsolete' => (bool)$image->getIsObsolete(),
|
||||
'isImage' => $file->isViewableImage(),
|
||||
'isViewable' => $file->isViewableInBrowser(),
|
||||
|
|
|
@ -5,10 +5,6 @@ final class PhortuneAddPaymentMethodAction
|
|||
|
||||
const TYPECONST = 'phortune.payment-method.add';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 60 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
|||
'subprojects/(?P<id>[1-9]\d*)/'
|
||||
=> 'PhabricatorProjectSubprojectsController',
|
||||
'board/(?P<id>[1-9]\d*)/'.
|
||||
'(?P<filter>filter/)?'.
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?'
|
||||
=> 'PhabricatorProjectBoardViewController',
|
||||
'move/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectMoveController',
|
||||
|
@ -80,6 +79,12 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
|||
=> 'PhabricatorProjectColumnHideController',
|
||||
'column/(?:(?P<id>\d+)/)?'
|
||||
=> 'PhabricatorProjectColumnDetailController',
|
||||
'viewquery/(?P<columnID>\d+)/'
|
||||
=> 'PhabricatorProjectColumnViewQueryController',
|
||||
'bulk/(?P<columnID>\d+)/'
|
||||
=> 'PhabricatorProjectColumnBulkEditController',
|
||||
'bulkmove/(?P<columnID>\d+)/(?P<mode>project|column)/'
|
||||
=> 'PhabricatorProjectColumnBulkMoveController',
|
||||
'import/'
|
||||
=> 'PhabricatorProjectBoardImportController',
|
||||
'reorder/'
|
||||
|
@ -90,6 +95,12 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
|||
=> 'PhabricatorProjectBoardManageController',
|
||||
'background/'
|
||||
=> 'PhabricatorProjectBoardBackgroundController',
|
||||
'default/(?P<target>[^/]+)/'
|
||||
=> 'PhabricatorProjectBoardDefaultController',
|
||||
'filter/(?:query/(?P<queryKey>[^/]+)/)?'
|
||||
=> 'PhabricatorProjectBoardFilterController',
|
||||
'reload/'
|
||||
=> 'PhabricatorProjectBoardReloadController',
|
||||
),
|
||||
'column/' => array(
|
||||
'remove/(?P<id>\d+)/' =>
|
||||
|
@ -112,8 +123,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
|||
=> 'PhabricatorProjectSilenceController',
|
||||
'warning/(?P<id>[1-9]\d*)/'
|
||||
=> 'PhabricatorProjectSubprojectWarningController',
|
||||
'default/(?P<projectID>[1-9]\d*)/(?P<target>[^/]+)/'
|
||||
=> 'PhabricatorProjectDefaultController',
|
||||
),
|
||||
'/tag/' => array(
|
||||
'(?P<slug>[^/]+)/' => 'PhabricatorProjectViewController',
|
||||
|
|
|
@ -1,4 +1,36 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorProjectBoardController
|
||||
extends PhabricatorProjectController {}
|
||||
extends PhabricatorProjectController {
|
||||
|
||||
private $viewState;
|
||||
|
||||
final protected function getViewState() {
|
||||
if ($this->viewState === null) {
|
||||
$this->viewState = $this->newViewState();
|
||||
}
|
||||
|
||||
return $this->viewState;
|
||||
}
|
||||
|
||||
private function newViewState() {
|
||||
$project = $this->getProject();
|
||||
$request = $this->getRequest();
|
||||
|
||||
return id(new PhabricatorWorkboardViewState())
|
||||
->setProject($project)
|
||||
->readFromRequest($request);
|
||||
}
|
||||
|
||||
final protected function newWorkboardDialog() {
|
||||
$dialog = $this->newDialog();
|
||||
|
||||
$state = $this->getViewState();
|
||||
foreach ($state->getQueryParameters() as $key => $value) {
|
||||
$dialog->addHiddenInput($key, $value);
|
||||
}
|
||||
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectDefaultController
|
||||
final class PhabricatorProjectBoardDefaultController
|
||||
extends PhabricatorProjectBoardController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$project_id = $request->getURIData('projectID');
|
||||
|
||||
$project = id(new PhabricatorProjectQuery())
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->withIDs(array($project_id))
|
||||
->executeOne();
|
||||
if (!$project) {
|
||||
return new Aphront404Response();
|
||||
$response = $this->loadProjectForEdit();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
$this->setProject($project);
|
||||
|
||||
$project = $this->getProject();
|
||||
$state = $this->getViewState();
|
||||
$board_uri = $state->newWorkboardURI();
|
||||
$remove_param = null;
|
||||
|
||||
$target = $request->getURIData('target');
|
||||
switch ($target) {
|
||||
|
@ -31,8 +26,10 @@ final class PhabricatorProjectDefaultController
|
|||
'the board.');
|
||||
$button = pht('Save Default Filter');
|
||||
|
||||
$xaction_value = $request->getStr('filter');
|
||||
$xaction_value = $state->getQueryKey();
|
||||
$xaction_type = PhabricatorProjectFilterTransaction::TRANSACTIONTYPE;
|
||||
|
||||
$remove_param = 'filter';
|
||||
break;
|
||||
case 'sort':
|
||||
$title = pht('Set Board Default Order');
|
||||
|
@ -42,8 +39,10 @@ final class PhabricatorProjectDefaultController
|
|||
'the board.');
|
||||
$button = pht('Save Default Order');
|
||||
|
||||
$xaction_value = $request->getStr('order');
|
||||
$xaction_value = $state->getOrder();
|
||||
$xaction_type = PhabricatorProjectSortTransaction::TRANSACTIONTYPE;
|
||||
|
||||
$remove_param = 'order';
|
||||
break;
|
||||
default:
|
||||
return new Aphront404Response();
|
||||
|
@ -51,12 +50,6 @@ final class PhabricatorProjectDefaultController
|
|||
|
||||
$id = $project->getID();
|
||||
|
||||
$view_uri = $this->getApplicationURI("board/{$id}/");
|
||||
$view_uri = new PhutilURI($view_uri);
|
||||
foreach ($request->getPassthroughRequestData() as $key => $value) {
|
||||
$view_uri->replaceQueryParam($key, $value);
|
||||
}
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$xactions = array();
|
||||
|
||||
|
@ -71,20 +64,18 @@ final class PhabricatorProjectDefaultController
|
|||
->setContinueOnMissingFields(true)
|
||||
->applyTransactions($project, $xactions);
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($view_uri);
|
||||
// If the parameter we just modified is present in the query string,
|
||||
// throw it away so the user is redirected back to the default view of
|
||||
// the board, allowing them to see the new default behavior.
|
||||
$board_uri->removeQueryParam($remove_param);
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($board_uri);
|
||||
}
|
||||
|
||||
$dialog = $this->newDialog()
|
||||
return $this->newWorkboardDialog()
|
||||
->setTitle($title)
|
||||
->appendChild($body)
|
||||
->setDisableWorkflowOnCancel(true)
|
||||
->addCancelButton($view_uri)
|
||||
->addCancelButton($board_uri)
|
||||
->addSubmitButton($title);
|
||||
|
||||
foreach ($request->getPassthroughRequestData() as $key => $value) {
|
||||
$dialog->addHiddenInput($key, $value);
|
||||
}
|
||||
|
||||
return $dialog;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectBoardFilterController
|
||||
extends PhabricatorProjectBoardController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$response = $this->loadProject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$project = $this->getProject();
|
||||
$state = $this->getViewState();
|
||||
$board_uri = $state->newWorkboardURI();
|
||||
|
||||
$search_engine = $state->getSearchEngine();
|
||||
|
||||
$is_submit = $request->isFormPost();
|
||||
|
||||
if ($is_submit) {
|
||||
$saved_query = $search_engine->buildSavedQueryFromRequest($request);
|
||||
$search_engine->saveQuery($saved_query);
|
||||
} else {
|
||||
$saved_query = $state->getSavedQuery();
|
||||
if (!$saved_query) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
}
|
||||
|
||||
$filter_form = id(new AphrontFormView())
|
||||
->setUser($viewer);
|
||||
|
||||
$search_engine->buildSearchForm($filter_form, $saved_query);
|
||||
|
||||
$errors = $search_engine->getErrors();
|
||||
|
||||
if ($is_submit && !$errors) {
|
||||
$query_key = $saved_query->getQueryKey();
|
||||
|
||||
$state->setQueryKey($query_key);
|
||||
$board_uri = $state->newWorkboardURI();
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($board_uri);
|
||||
}
|
||||
|
||||
return $this->newWorkboardDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FULL)
|
||||
->setTitle(pht('Advanced Filter'))
|
||||
->appendChild($filter_form->buildLayoutView())
|
||||
->setErrors($errors)
|
||||
->addSubmitButton(pht('Apply Filter'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectBoardReloadController
|
||||
extends PhabricatorProjectBoardController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$response = $this->loadProject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$order = $request->getStr('order');
|
||||
if (!strlen($order)) {
|
||||
$order = PhabricatorProjectColumnNaturalOrder::ORDERKEY;
|
||||
}
|
||||
|
||||
$ordering = PhabricatorProjectColumnOrder::getOrderByKey($order);
|
||||
$ordering = id(clone $ordering)
|
||||
->setViewer($viewer);
|
||||
|
||||
$project = $this->getProject();
|
||||
$state = $this->getViewState();
|
||||
$board_uri = $state->newWorkboardURI();
|
||||
|
||||
$layout_engine = $state->getLayoutEngine();
|
||||
|
||||
$board_phid = $project->getPHID();
|
||||
|
||||
$objects = $state->getObjects();
|
||||
$objects = mpull($objects, null, 'getPHID');
|
||||
|
||||
try {
|
||||
$client_state = $request->getStr('state');
|
||||
$client_state = phutil_json_decode($client_state);
|
||||
} catch (PhutilJSONParserException $ex) {
|
||||
$client_state = array();
|
||||
}
|
||||
|
||||
// Figure out which objects need to be updated: either the client has an
|
||||
// out-of-date version of them (objects which have been edited); or they
|
||||
// exist on the client but not on the server (objects which have been
|
||||
// removed from the board); or they exist on the server but not on the
|
||||
// client (objects which have been added to the board).
|
||||
|
||||
$update_objects = array();
|
||||
foreach ($objects as $object_phid => $object) {
|
||||
|
||||
// TODO: For now, this is always hard-coded.
|
||||
$object_version = 2;
|
||||
|
||||
$client_version = idx($client_state, $object_phid, 0);
|
||||
if ($object_version > $client_version) {
|
||||
$update_objects[$object_phid] = $object;
|
||||
}
|
||||
}
|
||||
|
||||
$update_phids = array_keys($update_objects);
|
||||
$visible_phids = array_keys($client_state);
|
||||
|
||||
$engine = id(new PhabricatorBoardResponseEngine())
|
||||
->setViewer($viewer)
|
||||
->setBoardPHID($board_phid)
|
||||
->setOrdering($ordering)
|
||||
->setObjects($objects)
|
||||
->setUpdatePHIDs($update_phids)
|
||||
->setVisiblePHIDs($visible_phids);
|
||||
|
||||
return $engine->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -3,14 +3,6 @@
|
|||
final class PhabricatorProjectBoardViewController
|
||||
extends PhabricatorProjectBoardController {
|
||||
|
||||
const BATCH_EDIT_ALL = 'all';
|
||||
|
||||
private $id;
|
||||
private $slug;
|
||||
private $queryKey;
|
||||
private $sortKey;
|
||||
private $showHidden;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
@ -24,120 +16,25 @@ final class PhabricatorProjectBoardViewController
|
|||
}
|
||||
|
||||
$project = $this->getProject();
|
||||
$state = $this->getViewState();
|
||||
$board_uri = $project->getWorkboardURI();
|
||||
|
||||
$this->readRequestState();
|
||||
|
||||
$board_uri = $this->getApplicationURI('board/'.$project->getID().'/');
|
||||
|
||||
$search_engine = id(new ManiphestTaskSearchEngine())
|
||||
->setViewer($viewer)
|
||||
->setBaseURI($board_uri)
|
||||
->setIsBoardView(true);
|
||||
|
||||
if ($request->isFormPost()
|
||||
&& !$request->getBool('initialize')
|
||||
&& !$request->getStr('move')
|
||||
&& !$request->getStr('queryColumnID')) {
|
||||
$saved = $search_engine->buildSavedQueryFromRequest($request);
|
||||
$search_engine->saveQuery($saved);
|
||||
$filter_form = id(new AphrontFormView())
|
||||
->setUser($viewer);
|
||||
$search_engine->buildSearchForm($filter_form, $saved);
|
||||
if ($search_engine->getErrors()) {
|
||||
return $this->newDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FULL)
|
||||
->setTitle(pht('Advanced Filter'))
|
||||
->appendChild($filter_form->buildLayoutView())
|
||||
->setErrors($search_engine->getErrors())
|
||||
->setSubmitURI($board_uri)
|
||||
->addSubmitButton(pht('Apply Filter'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
return id(new AphrontRedirectResponse())->setURI(
|
||||
$this->getURIWithState(
|
||||
$search_engine->getQueryResultsPageURI($saved->getQueryKey())));
|
||||
$search_engine = $state->getSearchEngine();
|
||||
$query_key = $state->getQueryKey();
|
||||
$saved = $state->getSavedQuery();
|
||||
if (!$saved) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$query_key = $this->getDefaultFilter($project);
|
||||
|
||||
$request_query = $request->getStr('filter');
|
||||
if (strlen($request_query)) {
|
||||
$query_key = $request_query;
|
||||
}
|
||||
|
||||
$uri_query = $request->getURIData('queryKey');
|
||||
if (strlen($uri_query)) {
|
||||
$query_key = $uri_query;
|
||||
}
|
||||
|
||||
$this->queryKey = $query_key;
|
||||
|
||||
$custom_query = null;
|
||||
if ($search_engine->isBuiltinQuery($query_key)) {
|
||||
$saved = $search_engine->buildSavedQueryFromBuiltin($query_key);
|
||||
} else {
|
||||
$saved = id(new PhabricatorSavedQueryQuery())
|
||||
->setViewer($viewer)
|
||||
->withQueryKeys(array($query_key))
|
||||
->executeOne();
|
||||
|
||||
if (!$saved) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($saved->getID()) {
|
||||
$custom_query = $saved;
|
||||
} else {
|
||||
$custom_query = null;
|
||||
}
|
||||
|
||||
if ($request->getURIData('filter')) {
|
||||
$filter_form = id(new AphrontFormView())
|
||||
->setUser($viewer);
|
||||
$search_engine->buildSearchForm($filter_form, $saved);
|
||||
|
||||
return $this->newDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FULL)
|
||||
->setTitle(pht('Advanced Filter'))
|
||||
->appendChild($filter_form->buildLayoutView())
|
||||
->setSubmitURI($board_uri)
|
||||
->addSubmitButton(pht('Apply Filter'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
|
||||
$task_query = $search_engine->buildQueryFromSavedQuery($saved);
|
||||
|
||||
$select_phids = array($project->getPHID());
|
||||
if ($project->getHasSubprojects() || $project->getHasMilestones()) {
|
||||
$descendants = id(new PhabricatorProjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withAncestorProjectPHIDs($select_phids)
|
||||
->execute();
|
||||
foreach ($descendants as $descendant) {
|
||||
$select_phids[] = $descendant->getPHID();
|
||||
}
|
||||
}
|
||||
|
||||
$tasks = $task_query
|
||||
->withEdgeLogicPHIDs(
|
||||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
|
||||
PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
|
||||
array($select_phids))
|
||||
->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)
|
||||
->setViewer($viewer)
|
||||
->execute();
|
||||
$tasks = mpull($tasks, null, 'getPHID');
|
||||
$layout_engine = $state->getLayoutEngine();
|
||||
|
||||
$board_phid = $project->getPHID();
|
||||
|
||||
// Regardless of display order, pass tasks to the layout engine in ID order
|
||||
// so layout is consistent.
|
||||
$board_tasks = msort($tasks, 'getID');
|
||||
|
||||
$layout_engine = id(new PhabricatorBoardLayoutEngine())
|
||||
->setViewer($viewer)
|
||||
->setBoardPHIDs(array($board_phid))
|
||||
->setObjectPHIDs(array_keys($board_tasks))
|
||||
->setFetchAllBoards(true)
|
||||
->executeLayout();
|
||||
|
||||
$columns = $layout_engine->getColumns($board_phid);
|
||||
if (!$columns || !$project->getHasWorkboard()) {
|
||||
$has_normal_columns = false;
|
||||
|
@ -190,307 +87,13 @@ final class PhabricatorProjectBoardViewController
|
|||
->appendChild($content);
|
||||
}
|
||||
|
||||
// If the user wants to turn a particular column into a query, build an
|
||||
// apropriate filter and redirect them to the query results page.
|
||||
$query_column_id = $request->getInt('queryColumnID');
|
||||
if ($query_column_id) {
|
||||
$column_id_map = mpull($columns, null, 'getID');
|
||||
$query_column = idx($column_id_map, $query_column_id);
|
||||
if (!$query_column) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
// Create a saved query to combine the active filter on the workboard
|
||||
// with the column filter. If the user currently has constraints on the
|
||||
// board, we want to add a new column or project constraint, not
|
||||
// completely replace the constraints.
|
||||
$saved_query = $saved->newCopy();
|
||||
|
||||
if ($query_column->getProxyPHID()) {
|
||||
$project_phids = $saved_query->getParameter('projectPHIDs');
|
||||
if (!$project_phids) {
|
||||
$project_phids = array();
|
||||
}
|
||||
$project_phids[] = $query_column->getProxyPHID();
|
||||
$saved_query->setParameter('projectPHIDs', $project_phids);
|
||||
} else {
|
||||
$saved_query->setParameter(
|
||||
'columnPHIDs',
|
||||
array($query_column->getPHID()));
|
||||
}
|
||||
|
||||
$search_engine = id(new ManiphestTaskSearchEngine())
|
||||
->setViewer($viewer);
|
||||
$search_engine->saveQuery($saved_query);
|
||||
|
||||
$query_key = $saved_query->getQueryKey();
|
||||
$query_uri = new PhutilURI("/maniphest/query/{$query_key}/#R");
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($query_uri);
|
||||
}
|
||||
$tasks = $state->getObjects();
|
||||
|
||||
$task_can_edit_map = id(new PhabricatorPolicyFilter())
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
|
||||
->apply($tasks);
|
||||
|
||||
// If this is a batch edit, select the editable tasks in the chosen column
|
||||
// and ship the user into the batch editor.
|
||||
$batch_edit = $request->getStr('batch');
|
||||
if ($batch_edit) {
|
||||
if ($batch_edit !== self::BATCH_EDIT_ALL) {
|
||||
$column_id_map = mpull($columns, null, 'getID');
|
||||
$batch_column = idx($column_id_map, $batch_edit);
|
||||
if (!$batch_column) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$batch_task_phids = $layout_engine->getColumnObjectPHIDs(
|
||||
$board_phid,
|
||||
$batch_column->getPHID());
|
||||
|
||||
foreach ($batch_task_phids as $key => $batch_task_phid) {
|
||||
if (empty($task_can_edit_map[$batch_task_phid])) {
|
||||
unset($batch_task_phids[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$batch_tasks = array_select_keys($tasks, $batch_task_phids);
|
||||
} else {
|
||||
$batch_tasks = $task_can_edit_map;
|
||||
}
|
||||
|
||||
if (!$batch_tasks) {
|
||||
$cancel_uri = $this->getURIWithState($board_uri);
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('No Editable Tasks'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'The selected column contains no visible tasks which you '.
|
||||
'have permission to edit.'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
|
||||
// Create a saved query to hold the working set. This allows us to get
|
||||
// around URI length limitations with a long "?ids=..." query string.
|
||||
// For details, see T10268.
|
||||
$search_engine = id(new ManiphestTaskSearchEngine())
|
||||
->setViewer($viewer);
|
||||
|
||||
$saved_query = $search_engine->newSavedQuery();
|
||||
$saved_query->setParameter('ids', mpull($batch_tasks, 'getID'));
|
||||
$search_engine->saveQuery($saved_query);
|
||||
|
||||
$query_key = $saved_query->getQueryKey();
|
||||
|
||||
$bulk_uri = new PhutilURI("/maniphest/bulk/query/{$query_key}/");
|
||||
$bulk_uri->replaceQueryParam('board', $this->id);
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($bulk_uri);
|
||||
}
|
||||
|
||||
$move_id = $request->getStr('move');
|
||||
if (strlen($move_id)) {
|
||||
$column_id_map = mpull($columns, null, 'getID');
|
||||
$move_column = idx($column_id_map, $move_id);
|
||||
if (!$move_column) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$move_task_phids = $layout_engine->getColumnObjectPHIDs(
|
||||
$board_phid,
|
||||
$move_column->getPHID());
|
||||
|
||||
foreach ($move_task_phids as $key => $move_task_phid) {
|
||||
if (empty($task_can_edit_map[$move_task_phid])) {
|
||||
unset($move_task_phids[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$move_tasks = array_select_keys($tasks, $move_task_phids);
|
||||
$cancel_uri = $this->getURIWithState($board_uri);
|
||||
|
||||
if (!$move_tasks) {
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('No Movable Tasks'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'The selected column contains no visible tasks which you '.
|
||||
'have permission to move.'))
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
|
||||
$move_project_phid = $project->getPHID();
|
||||
$move_column_phid = null;
|
||||
$move_project = null;
|
||||
$move_column = null;
|
||||
$columns = null;
|
||||
$errors = array();
|
||||
|
||||
if ($request->isFormOrHiSecPost()) {
|
||||
$move_project_phid = head($request->getArr('moveProjectPHID'));
|
||||
if (!$move_project_phid) {
|
||||
$move_project_phid = $request->getStr('moveProjectPHID');
|
||||
}
|
||||
|
||||
if (!$move_project_phid) {
|
||||
if ($request->getBool('hasProject')) {
|
||||
$errors[] = pht('Choose a project to move tasks to.');
|
||||
}
|
||||
} else {
|
||||
$target_project = id(new PhabricatorProjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($move_project_phid))
|
||||
->executeOne();
|
||||
if (!$target_project) {
|
||||
$errors[] = pht('You must choose a valid project.');
|
||||
} else if (!$project->getHasWorkboard()) {
|
||||
$errors[] = pht(
|
||||
'You must choose a project with a workboard.');
|
||||
} else {
|
||||
$move_project = $target_project;
|
||||
}
|
||||
}
|
||||
|
||||
if ($move_project) {
|
||||
$move_engine = id(new PhabricatorBoardLayoutEngine())
|
||||
->setViewer($viewer)
|
||||
->setBoardPHIDs(array($move_project->getPHID()))
|
||||
->setFetchAllBoards(true)
|
||||
->executeLayout();
|
||||
|
||||
$columns = $move_engine->getColumns($move_project->getPHID());
|
||||
$columns = mpull($columns, null, 'getPHID');
|
||||
|
||||
foreach ($columns as $key => $column) {
|
||||
if ($column->isHidden()) {
|
||||
unset($columns[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$move_column_phid = $request->getStr('moveColumnPHID');
|
||||
if (!$move_column_phid) {
|
||||
if ($request->getBool('hasColumn')) {
|
||||
$errors[] = pht('Choose a column to move tasks to.');
|
||||
}
|
||||
} else {
|
||||
if (empty($columns[$move_column_phid])) {
|
||||
$errors[] = pht(
|
||||
'Choose a valid column on the target workboard to move '.
|
||||
'tasks to.');
|
||||
} else if ($columns[$move_column_phid]->getID() == $move_id) {
|
||||
$errors[] = pht(
|
||||
'You can not move tasks from a column to itself.');
|
||||
} else {
|
||||
$move_column = $columns[$move_column_phid];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($move_column && $move_project) {
|
||||
foreach ($move_tasks as $move_task) {
|
||||
$xactions = array();
|
||||
|
||||
// If we're switching projects, get out of the old project first
|
||||
// and move to the new project.
|
||||
if ($move_project->getID() != $project->getID()) {
|
||||
$xactions[] = id(new ManiphestTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
|
||||
->setMetadataValue(
|
||||
'edge:type',
|
||||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
|
||||
->setNewValue(
|
||||
array(
|
||||
'-' => array(
|
||||
$project->getPHID() => $project->getPHID(),
|
||||
),
|
||||
'+' => array(
|
||||
$move_project->getPHID() => $move_project->getPHID(),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$xactions[] = id(new ManiphestTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)
|
||||
->setNewValue(
|
||||
array(
|
||||
array(
|
||||
'columnPHID' => $move_column->getPHID(),
|
||||
),
|
||||
));
|
||||
|
||||
$editor = id(new ManiphestTransactionEditor())
|
||||
->setActor($viewer)
|
||||
->setContinueOnMissingFields(true)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setCancelURI($cancel_uri);
|
||||
|
||||
$editor->applyTransactions($move_task, $xactions);
|
||||
}
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($cancel_uri);
|
||||
}
|
||||
|
||||
if ($move_project) {
|
||||
$column_form = id(new AphrontFormView())
|
||||
->setViewer($viewer)
|
||||
->appendControl(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setName('moveColumnPHID')
|
||||
->setLabel(pht('Move to Column'))
|
||||
->setValue($move_column_phid)
|
||||
->setOptions(mpull($columns, 'getDisplayName', 'getPHID')));
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Move Tasks'))
|
||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||
->setErrors($errors)
|
||||
->addHiddenInput('move', $move_id)
|
||||
->addHiddenInput('moveProjectPHID', $move_project->getPHID())
|
||||
->addHiddenInput('hasColumn', true)
|
||||
->addHiddenInput('hasProject', true)
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'Choose a column on the %s workboard to move tasks to:',
|
||||
$viewer->renderHandle($move_project->getPHID())))
|
||||
->appendForm($column_form)
|
||||
->addSubmitButton(pht('Move Tasks'))
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
|
||||
if ($move_project_phid) {
|
||||
$move_project_phid_value = array($move_project_phid);
|
||||
} else {
|
||||
$move_project_phid_value = array();
|
||||
}
|
||||
|
||||
$project_form = id(new AphrontFormView())
|
||||
->setViewer($viewer)
|
||||
->appendControl(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setName('moveProjectPHID')
|
||||
->setLimit(1)
|
||||
->setLabel(pht('Move to Project'))
|
||||
->setValue($move_project_phid_value)
|
||||
->setDatasource(new PhabricatorProjectDatasource()));
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Move Tasks'))
|
||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||
->setErrors($errors)
|
||||
->addHiddenInput('move', $move_id)
|
||||
->addHiddenInput('hasProject', true)
|
||||
->appendForm($project_form)
|
||||
->addSubmitButton(pht('Continue'))
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
|
||||
|
||||
$board_id = celerity_generate_unique_node_id();
|
||||
|
||||
$board = id(new PHUIWorkboardView())
|
||||
|
@ -506,7 +109,7 @@ final class PhabricatorProjectBoardViewController
|
|||
$column_phids = array();
|
||||
$visible_phids = array();
|
||||
foreach ($columns as $column) {
|
||||
if (!$this->showHidden) {
|
||||
if (!$state->getShowHidden()) {
|
||||
if ($column->isHidden()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -534,11 +137,13 @@ final class PhabricatorProjectBoardViewController
|
|||
}
|
||||
}
|
||||
|
||||
$container_phids = $state->getBoardContainerPHIDs();
|
||||
|
||||
$rendering_engine = id(new PhabricatorBoardRenderingEngine())
|
||||
->setViewer($viewer)
|
||||
->setObjects(array_select_keys($tasks, $visible_phids))
|
||||
->setEditMap($task_can_edit_map)
|
||||
->setExcludedProjectPHIDs($select_phids);
|
||||
->setExcludedProjectPHIDs($container_phids);
|
||||
|
||||
$templates = array();
|
||||
$all_tasks = array();
|
||||
|
@ -651,7 +256,7 @@ final class PhabricatorProjectBoardViewController
|
|||
);
|
||||
}
|
||||
|
||||
$order_key = $this->sortKey;
|
||||
$order_key = $state->getOrder();
|
||||
|
||||
$ordering_map = PhabricatorProjectColumnOrder::getEnabledOrders();
|
||||
$ordering = id(clone $ordering_map[$order_key])
|
||||
|
@ -681,11 +286,12 @@ final class PhabricatorProjectBoardViewController
|
|||
'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'),
|
||||
'uploadURI' => '/file/dropupload/',
|
||||
'coverURI' => $this->getApplicationURI('cover/'),
|
||||
'reloadURI' => phutil_string_cast($state->newWorkboardURI('reload/')),
|
||||
'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(),
|
||||
'pointsEnabled' => ManiphestTaskPoints::getIsEnabled(),
|
||||
|
||||
'boardPHID' => $project->getPHID(),
|
||||
'order' => $this->sortKey,
|
||||
'order' => $state->getOrder(),
|
||||
'orders' => $order_maps,
|
||||
'headers' => $headers,
|
||||
'headerKeys' => $header_keys,
|
||||
|
@ -703,7 +309,7 @@ final class PhabricatorProjectBoardViewController
|
|||
$sort_menu = $this->buildSortMenu(
|
||||
$viewer,
|
||||
$project,
|
||||
$this->sortKey,
|
||||
$state->getOrder(),
|
||||
$ordering_map);
|
||||
|
||||
$filter_menu = $this->buildFilterMenu(
|
||||
|
@ -713,7 +319,7 @@ final class PhabricatorProjectBoardViewController
|
|||
$search_engine,
|
||||
$query_key);
|
||||
|
||||
$manage_menu = $this->buildManageMenu($project, $this->showHidden);
|
||||
$manage_menu = $this->buildManageMenu($project, $state->getShowHidden());
|
||||
|
||||
$header_link = phutil_tag(
|
||||
'a',
|
||||
|
@ -777,55 +383,14 @@ final class PhabricatorProjectBoardViewController
|
|||
return $page;
|
||||
}
|
||||
|
||||
private function readRequestState() {
|
||||
$request = $this->getRequest();
|
||||
$project = $this->getProject();
|
||||
|
||||
$this->showHidden = $request->getBool('hidden');
|
||||
$this->id = $project->getID();
|
||||
|
||||
$sort_key = $this->getDefaultSort($project);
|
||||
|
||||
$request_sort = $request->getStr('order');
|
||||
if ($this->isValidSort($request_sort)) {
|
||||
$sort_key = $request_sort;
|
||||
}
|
||||
|
||||
$this->sortKey = $sort_key;
|
||||
}
|
||||
|
||||
private function getDefaultSort(PhabricatorProject $project) {
|
||||
$default_sort = $project->getDefaultWorkboardSort();
|
||||
|
||||
if ($this->isValidSort($default_sort)) {
|
||||
return $default_sort;
|
||||
}
|
||||
|
||||
return PhabricatorProjectColumnNaturalOrder::ORDERKEY;
|
||||
}
|
||||
|
||||
private function getDefaultFilter(PhabricatorProject $project) {
|
||||
$default_filter = $project->getDefaultWorkboardFilter();
|
||||
|
||||
if (strlen($default_filter)) {
|
||||
return $default_filter;
|
||||
}
|
||||
|
||||
return 'open';
|
||||
}
|
||||
|
||||
private function isValidSort($sort) {
|
||||
$map = PhabricatorProjectColumnOrder::getEnabledOrders();
|
||||
return isset($map[$sort]);
|
||||
}
|
||||
|
||||
private function buildSortMenu(
|
||||
PhabricatorUser $viewer,
|
||||
PhabricatorProject $project,
|
||||
$sort_key,
|
||||
array $ordering_map) {
|
||||
|
||||
$base_uri = $this->getURIWithState();
|
||||
$state = $this->getViewState();
|
||||
$base_uri = $state->newWorkboardURI();
|
||||
|
||||
$items = array();
|
||||
foreach ($ordering_map as $key => $ordering) {
|
||||
|
@ -855,9 +420,7 @@ final class PhabricatorProjectBoardViewController
|
|||
|
||||
$id = $project->getID();
|
||||
|
||||
$save_uri = "default/{$id}/sort/";
|
||||
$save_uri = $this->getApplicationURI($save_uri);
|
||||
$save_uri = $this->getURIWithState($save_uri, $force = true);
|
||||
$save_uri = $state->newWorkboardURI('default/sort/');
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
|
@ -900,6 +463,8 @@ final class PhabricatorProjectBoardViewController
|
|||
PhabricatorApplicationSearchEngine $engine,
|
||||
$query_key) {
|
||||
|
||||
$state = $this->getViewState();
|
||||
|
||||
$named = array(
|
||||
'open' => pht('Open Tasks'),
|
||||
'all' => pht('All Tasks'),
|
||||
|
@ -931,24 +496,26 @@ final class PhabricatorProjectBoardViewController
|
|||
->setName($name);
|
||||
|
||||
if ($is_custom) {
|
||||
$uri = $this->getApplicationURI(
|
||||
'board/'.$this->id.'/filter/query/'.$key.'/');
|
||||
// When you're using a custom filter already and you select "Custom
|
||||
// Filter", you get a dialog back to let you edit the filter. This is
|
||||
// equivalent to selecting "Advanced Filter..." to configure a new
|
||||
// filter.
|
||||
$filter_uri = $state->newWorkboardURI('filter/');
|
||||
$item->setWorkflow(true);
|
||||
} else {
|
||||
$uri = $engine->getQueryResultsPageURI($key);
|
||||
$filter_uri = urisprintf('query/%s/', $key);
|
||||
$filter_uri = $state->newWorkboardURI($filter_uri);
|
||||
$filter_uri->removeQueryParam('filter');
|
||||
}
|
||||
|
||||
$uri = $this->getURIWithState($uri)
|
||||
->removeQueryParam('filter');
|
||||
$item->setHref($uri);
|
||||
$item->setHref($filter_uri);
|
||||
|
||||
$items[] = $item;
|
||||
}
|
||||
|
||||
$id = $project->getID();
|
||||
|
||||
$filter_uri = $this->getApplicationURI("board/{$id}/filter/");
|
||||
$filter_uri = $this->getURIWithState($filter_uri, $force = true);
|
||||
$filter_uri = $state->newWorkboardURI('filter/');
|
||||
|
||||
$items[] = id(new PhabricatorActionView())
|
||||
->setIcon('fa-cog')
|
||||
|
@ -956,9 +523,7 @@ final class PhabricatorProjectBoardViewController
|
|||
->setWorkflow(true)
|
||||
->setName(pht('Advanced Filter...'));
|
||||
|
||||
$save_uri = "default/{$id}/filter/";
|
||||
$save_uri = $this->getApplicationURI($save_uri);
|
||||
$save_uri = $this->getURIWithState($save_uri, $force = true);
|
||||
$save_uri = $state->newWorkboardURI('default/filter/');
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
|
@ -1000,6 +565,7 @@ final class PhabricatorProjectBoardViewController
|
|||
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
$state = $this->getViewState();
|
||||
|
||||
$id = $project->getID();
|
||||
|
||||
|
@ -1029,12 +595,12 @@ final class PhabricatorProjectBoardViewController
|
|||
->setWorkflow(true);
|
||||
|
||||
if ($show_hidden) {
|
||||
$hidden_uri = $this->getURIWithState()
|
||||
$hidden_uri = $state->newWorkboardURI()
|
||||
->removeQueryParam('hidden');
|
||||
$hidden_icon = 'fa-eye-slash';
|
||||
$hidden_text = pht('Hide Hidden Columns');
|
||||
} else {
|
||||
$hidden_uri = $this->getURIWithState()
|
||||
$hidden_uri = $state->newWorkboardURI()
|
||||
->replaceQueryParam('hidden', 'true');
|
||||
$hidden_icon = 'fa-eye';
|
||||
$hidden_text = pht('Show Hidden Columns');
|
||||
|
@ -1062,13 +628,6 @@ final class PhabricatorProjectBoardViewController
|
|||
->setName(pht('Manage Workboard'))
|
||||
->setHref($manage_uri);
|
||||
|
||||
$batch_edit_uri = $request->getRequestURI();
|
||||
$batch_edit_uri->replaceQueryParam('batch', self::BATCH_EDIT_ALL);
|
||||
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
|
||||
ManiphestBulkEditCapability::CAPABILITY);
|
||||
|
||||
$manage_menu = id(new PhabricatorActionListView())
|
||||
->setUser($viewer);
|
||||
foreach ($manage_items as $item) {
|
||||
|
@ -1114,6 +673,7 @@ final class PhabricatorProjectBoardViewController
|
|||
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
$state = $this->getViewState();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
|
@ -1151,36 +711,51 @@ final class PhabricatorProjectBoardViewController
|
|||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setType(PhabricatorActionView::TYPE_DIVIDER);
|
||||
|
||||
$batch_edit_uri = $request->getRequestURI();
|
||||
$batch_edit_uri->replaceQueryParam('batch', $column->getID());
|
||||
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$query_uri = urisprintf('viewquery/%d/', $column->getID());
|
||||
$query_uri = $state->newWorkboardURI($query_uri);
|
||||
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setName(pht('View Tasks as Query'))
|
||||
->setIcon('fa-search')
|
||||
->setHref($query_uri);
|
||||
|
||||
$column_move_uri = urisprintf('bulkmove/%d/column/', $column->getID());
|
||||
$column_move_uri = $state->newWorkboardURI($column_move_uri);
|
||||
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setIcon('fa-arrows-h')
|
||||
->setName(pht('Move Tasks to Column...'))
|
||||
->setHref($column_move_uri)
|
||||
->setWorkflow(true);
|
||||
|
||||
$project_move_uri = urisprintf('bulkmove/%d/project/', $column->getID());
|
||||
$project_move_uri = $state->newWorkboardURI($project_move_uri);
|
||||
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setIcon('fa-arrows')
|
||||
->setName(pht('Move Tasks to Project...'))
|
||||
->setHref($project_move_uri)
|
||||
->setWorkflow(true);
|
||||
|
||||
$bulk_edit_uri = urisprintf('bulk/%d/', $column->getID());
|
||||
$bulk_edit_uri = $state->newWorkboardURI($bulk_edit_uri);
|
||||
|
||||
$can_bulk_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
|
||||
ManiphestBulkEditCapability::CAPABILITY);
|
||||
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setIcon('fa-list-ul')
|
||||
->setIcon('fa-pencil-square-o')
|
||||
->setName(pht('Bulk Edit Tasks...'))
|
||||
->setHref($batch_edit_uri)
|
||||
->setDisabled(!$can_batch_edit);
|
||||
|
||||
$batch_move_uri = $request->getRequestURI();
|
||||
$batch_move_uri->replaceQueryParam('move', $column->getID());
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setIcon('fa-arrow-right')
|
||||
->setName(pht('Move Tasks to Column...'))
|
||||
->setHref($batch_move_uri)
|
||||
->setWorkflow(true);
|
||||
|
||||
$query_uri = $request->getRequestURI();
|
||||
$query_uri->replaceQueryParam('queryColumnID', $column->getID());
|
||||
->setHref($bulk_edit_uri)
|
||||
->setDisabled(!$can_bulk_edit);
|
||||
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setName(pht('View as Query'))
|
||||
->setIcon('fa-search')
|
||||
->setHref($query_uri);
|
||||
->setType(PhabricatorActionView::TYPE_DIVIDER);
|
||||
|
||||
$edit_uri = 'board/'.$this->id.'/edit/'.$column->getID().'/';
|
||||
|
||||
$edit_uri = 'board/'.$project->getID().'/edit/'.$column->getID().'/';
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Column'))
|
||||
->setIcon('fa-pencil')
|
||||
|
@ -1189,9 +764,9 @@ final class PhabricatorProjectBoardViewController
|
|||
->setWorkflow(true);
|
||||
|
||||
$can_hide = ($can_edit && !$column->isDefaultColumn());
|
||||
$hide_uri = 'board/'.$this->id.'/hide/'.$column->getID().'/';
|
||||
$hide_uri = $this->getApplicationURI($hide_uri);
|
||||
$hide_uri = $this->getURIWithState($hide_uri);
|
||||
|
||||
$hide_uri = urisprintf('hide/%d/', $column->getID());
|
||||
$hide_uri = $state->newWorkboardURI($hide_uri);
|
||||
|
||||
if (!$column->isHidden()) {
|
||||
$column_items[] = id(new PhabricatorActionView())
|
||||
|
@ -1297,56 +872,6 @@ final class PhabricatorProjectBoardViewController
|
|||
return $trigger_button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add current state parameters (like order and the visibility of hidden
|
||||
* columns) to a URI.
|
||||
*
|
||||
* This allows actions which toggle or adjust one piece of state to keep
|
||||
* the rest of the board state persistent. If no URI is provided, this method
|
||||
* starts with the request URI.
|
||||
*
|
||||
* @param string|null URI to add state parameters to.
|
||||
* @param bool True to explicitly include all state.
|
||||
* @return PhutilURI URI with state parameters.
|
||||
*/
|
||||
private function getURIWithState($base = null, $force = false) {
|
||||
$project = $this->getProject();
|
||||
|
||||
if ($base === null) {
|
||||
$base = $this->getRequest()->getPath();
|
||||
}
|
||||
|
||||
$base = new PhutilURI($base);
|
||||
|
||||
if ($force || ($this->sortKey != $this->getDefaultSort($project))) {
|
||||
if ($this->sortKey !== null) {
|
||||
$base->replaceQueryParam('order', $this->sortKey);
|
||||
} else {
|
||||
$base->removeQueryParam('order');
|
||||
}
|
||||
} else {
|
||||
$base->removeQueryParam('order');
|
||||
}
|
||||
|
||||
if ($force || ($this->queryKey != $this->getDefaultFilter($project))) {
|
||||
if ($this->queryKey !== null) {
|
||||
$base->replaceQueryParam('filter', $this->queryKey);
|
||||
} else {
|
||||
$base->removeQueryParam('filter');
|
||||
}
|
||||
} else {
|
||||
$base->removeQueryParam('filter');
|
||||
}
|
||||
|
||||
if ($this->showHidden) {
|
||||
$base->replaceQueryParam('hidden', 'true');
|
||||
} else {
|
||||
$base->removeQueryParam('hidden');
|
||||
}
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
private function buildInitializeContent(PhabricatorProject $project) {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $this->getViewer();
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectColumnBulkEditController
|
||||
extends PhabricatorProjectBoardController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$response = $this->loadProject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$project = $this->getProject();
|
||||
$state = $this->getViewState();
|
||||
$board_uri = $state->newWorkboardURI();
|
||||
|
||||
$layout_engine = $state->getLayoutEngine();
|
||||
|
||||
$board_phid = $project->getPHID();
|
||||
$columns = $layout_engine->getColumns($board_phid);
|
||||
$columns = mpull($columns, null, 'getID');
|
||||
|
||||
$column_id = $request->getURIData('columnID');
|
||||
$bulk_column = idx($columns, $column_id);
|
||||
if (!$bulk_column) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$bulk_task_phids = $layout_engine->getColumnObjectPHIDs(
|
||||
$board_phid,
|
||||
$bulk_column->getPHID());
|
||||
|
||||
$tasks = $state->getObjects();
|
||||
|
||||
$bulk_tasks = array_select_keys($tasks, $bulk_task_phids);
|
||||
|
||||
$bulk_tasks = id(new PhabricatorPolicyFilter())
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
|
||||
->apply($bulk_tasks);
|
||||
|
||||
if (!$bulk_tasks) {
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('No Editable Tasks'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'The selected column contains no visible tasks which you '.
|
||||
'have permission to edit.'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
|
||||
// Create a saved query to hold the working set. This allows us to get
|
||||
// around URI length limitations with a long "?ids=..." query string.
|
||||
// For details, see T10268.
|
||||
$search_engine = id(new ManiphestTaskSearchEngine())
|
||||
->setViewer($viewer);
|
||||
|
||||
$saved_query = $search_engine->newSavedQuery();
|
||||
$saved_query->setParameter('ids', mpull($bulk_tasks, 'getID'));
|
||||
$search_engine->saveQuery($saved_query);
|
||||
|
||||
$query_key = $saved_query->getQueryKey();
|
||||
|
||||
$bulk_uri = new PhutilURI("/maniphest/bulk/query/{$query_key}/");
|
||||
$bulk_uri->replaceQueryParam('board', $project->getID());
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($bulk_uri);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectColumnBulkMoveController
|
||||
extends PhabricatorProjectBoardController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$response = $this->loadProject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// See T13316. If we're operating in "column" mode, we're going to skip
|
||||
// the prompt for a project and just have the user select a target column.
|
||||
// In "project" mode, we prompt them for a project first.
|
||||
$is_column_mode = ($request->getURIData('mode') === 'column');
|
||||
|
||||
$src_project = $this->getProject();
|
||||
$state = $this->getViewState();
|
||||
$board_uri = $state->newWorkboardURI();
|
||||
|
||||
$layout_engine = $state->getLayoutEngine();
|
||||
|
||||
$board_phid = $src_project->getPHID();
|
||||
$columns = $layout_engine->getColumns($board_phid);
|
||||
$columns = mpull($columns, null, 'getID');
|
||||
|
||||
$column_id = $request->getURIData('columnID');
|
||||
$src_column = idx($columns, $column_id);
|
||||
if (!$src_column) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$move_task_phids = $layout_engine->getColumnObjectPHIDs(
|
||||
$board_phid,
|
||||
$src_column->getPHID());
|
||||
|
||||
$tasks = $state->getObjects();
|
||||
|
||||
$move_tasks = array_select_keys($tasks, $move_task_phids);
|
||||
|
||||
$move_tasks = id(new PhabricatorPolicyFilter())
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
|
||||
->apply($move_tasks);
|
||||
|
||||
if (!$move_tasks) {
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('No Movable Tasks'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'The selected column contains no visible tasks which you '.
|
||||
'have permission to move.'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
|
||||
$dst_project_phid = null;
|
||||
$dst_project = null;
|
||||
$has_project = false;
|
||||
if ($is_column_mode) {
|
||||
$has_project = true;
|
||||
$dst_project_phid = $src_project->getPHID();
|
||||
} else {
|
||||
if ($request->isFormOrHiSecPost()) {
|
||||
$has_project = $request->getStr('hasProject');
|
||||
if ($has_project) {
|
||||
// We may read this from a tokenizer input as an array, or from a
|
||||
// hidden input as a string.
|
||||
$dst_project_phid = head($request->getArr('dstProjectPHID'));
|
||||
if (!$dst_project_phid) {
|
||||
$dst_project_phid = $request->getStr('dstProjectPHID');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
$hidden = array();
|
||||
|
||||
if ($has_project) {
|
||||
if (!$dst_project_phid) {
|
||||
$errors[] = pht('Choose a project to move tasks to.');
|
||||
} else {
|
||||
$dst_project = id(new PhabricatorProjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($dst_project_phid))
|
||||
->executeOne();
|
||||
if (!$dst_project) {
|
||||
$errors[] = pht('Choose a valid project to move tasks to.');
|
||||
}
|
||||
|
||||
if (!$dst_project->getHasWorkboard()) {
|
||||
$errors[] = pht('You must choose a project with a workboard.');
|
||||
$dst_project = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($dst_project) {
|
||||
$same_project = ($src_project->getID() === $dst_project->getID());
|
||||
|
||||
$layout_engine = id(new PhabricatorBoardLayoutEngine())
|
||||
->setViewer($viewer)
|
||||
->setBoardPHIDs(array($dst_project->getPHID()))
|
||||
->setFetchAllBoards(true)
|
||||
->executeLayout();
|
||||
|
||||
$dst_columns = $layout_engine->getColumns($dst_project->getPHID());
|
||||
$dst_columns = mpull($columns, null, 'getPHID');
|
||||
|
||||
$has_column = false;
|
||||
$dst_column = null;
|
||||
|
||||
// If we're performing a move on the same board, default the
|
||||
// control value to the current column.
|
||||
if ($same_project) {
|
||||
$dst_column_phid = $src_column->getPHID();
|
||||
} else {
|
||||
$dst_column_phid = null;
|
||||
}
|
||||
|
||||
if ($request->isFormOrHiSecPost()) {
|
||||
$has_column = $request->getStr('hasColumn');
|
||||
if ($has_column) {
|
||||
$dst_column_phid = $request->getStr('dstColumnPHID');
|
||||
}
|
||||
}
|
||||
|
||||
if ($has_column) {
|
||||
$dst_column = idx($dst_columns, $dst_column_phid);
|
||||
if (!$dst_column) {
|
||||
$errors[] = pht('Choose a column to move tasks to.');
|
||||
} else {
|
||||
if ($dst_column->isHidden()) {
|
||||
$errors[] = pht('You can not move tasks to a hidden column.');
|
||||
$dst_column = null;
|
||||
} else if ($dst_column->getPHID() === $src_column->getPHID()) {
|
||||
$errors[] = pht('You can not move tasks from a column to itself.');
|
||||
$dst_column = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($dst_column) {
|
||||
foreach ($move_tasks as $move_task) {
|
||||
$xactions = array();
|
||||
|
||||
// If we're switching projects, get out of the old project first
|
||||
// and move to the new project.
|
||||
if (!$same_project) {
|
||||
$xactions[] = id(new ManiphestTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
|
||||
->setMetadataValue(
|
||||
'edge:type',
|
||||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
|
||||
->setNewValue(
|
||||
array(
|
||||
'-' => array(
|
||||
$src_project->getPHID() => $src_project->getPHID(),
|
||||
),
|
||||
'+' => array(
|
||||
$dst_project->getPHID() => $dst_project->getPHID(),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$xactions[] = id(new ManiphestTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)
|
||||
->setNewValue(
|
||||
array(
|
||||
array(
|
||||
'columnPHID' => $dst_column->getPHID(),
|
||||
),
|
||||
));
|
||||
|
||||
$editor = id(new ManiphestTransactionEditor())
|
||||
->setActor($viewer)
|
||||
->setContinueOnMissingFields(true)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setCancelURI($board_uri);
|
||||
|
||||
$editor->applyTransactions($move_task, $xactions);
|
||||
}
|
||||
|
||||
// If we did a move on the same workboard, redirect and preserve the
|
||||
// state parameters. If we moved to a different workboard, go there
|
||||
// with clean default state.
|
||||
if ($same_project) {
|
||||
$done_uri = $board_uri;
|
||||
} else {
|
||||
$done_uri = $dst_project->getWorkboardURI();
|
||||
}
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||
}
|
||||
|
||||
$title = pht('Move Tasks to Column');
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setViewer($viewer);
|
||||
|
||||
// If we're moving between projects, add a reminder about which project
|
||||
// you selected in the previous step.
|
||||
if (!$is_column_mode) {
|
||||
$form->appendControl(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel(pht('Project'))
|
||||
->setValue($dst_project->getDisplayName()));
|
||||
}
|
||||
|
||||
$form->appendControl(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setName('dstColumnPHID')
|
||||
->setLabel(pht('Move to Column'))
|
||||
->setValue($dst_column_phid)
|
||||
->setOptions(mpull($dst_columns, 'getDisplayName', 'getPHID')));
|
||||
|
||||
$submit = pht('Move Tasks');
|
||||
|
||||
$hidden['dstProjectPHID'] = $dst_project->getPHID();
|
||||
$hidden['hasColumn'] = true;
|
||||
$hidden['hasProject'] = true;
|
||||
} else {
|
||||
$title = pht('Move Tasks to Project');
|
||||
|
||||
if ($dst_project_phid) {
|
||||
$dst_project_phid_value = array($dst_project_phid);
|
||||
} else {
|
||||
$dst_project_phid_value = array();
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setViewer($viewer)
|
||||
->appendControl(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setName('dstProjectPHID')
|
||||
->setLimit(1)
|
||||
->setLabel(pht('Move to Project'))
|
||||
->setValue($dst_project_phid_value)
|
||||
->setDatasource(new PhabricatorProjectDatasource()));
|
||||
|
||||
$submit = pht('Continue');
|
||||
|
||||
$hidden['hasProject'] = true;
|
||||
}
|
||||
|
||||
$dialog = $this->newWorkboardDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||
->setTitle($title)
|
||||
->setErrors($errors)
|
||||
->appendForm($form)
|
||||
->addSubmitButton($submit)
|
||||
->addCancelButton($board_uri);
|
||||
|
||||
foreach ($hidden as $key => $value) {
|
||||
$dialog->addHiddenInput($key, $value);
|
||||
}
|
||||
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue