2011-01-16 13:51:39 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright 2011 Facebook, Inc.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @group aphront
|
|
|
|
*/
|
|
|
|
class AphrontDefaultApplicationConfiguration
|
|
|
|
extends AphrontApplicationConfiguration {
|
|
|
|
|
2011-02-24 14:52:57 -08:00
|
|
|
public function __construct() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-01-16 13:51:39 -08:00
|
|
|
public function getApplicationName() {
|
|
|
|
return 'aphront-default';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getURIMap() {
|
2011-02-24 14:52:57 -08:00
|
|
|
return $this->getResourceURIMapRules() + array(
|
2011-01-16 13:51:39 -08:00
|
|
|
'/' => array(
|
2011-01-22 21:09:13 -08:00
|
|
|
'$' => 'PhabricatorDirectoryMainController',
|
2011-01-16 13:51:39 -08:00
|
|
|
),
|
|
|
|
'/directory/' => array(
|
2011-01-22 21:09:13 -08:00
|
|
|
'item/$'
|
|
|
|
=> 'PhabricatorDirectoryItemListController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'item/edit/(?:(?P<id>\d+)/)?$'
|
2011-01-22 21:09:13 -08:00
|
|
|
=> 'PhabricatorDirectoryItemEditController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'item/delete/(?P<id>\d+)/'
|
2011-01-22 21:09:13 -08:00
|
|
|
=> 'PhabricatorDirectoryItemDeleteController',
|
2011-01-16 13:51:39 -08:00
|
|
|
'category/$'
|
2011-01-22 21:09:13 -08:00
|
|
|
=> 'PhabricatorDirectoryCategoryListController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'category/edit/(?:(?P<id>\d+)/)?$'
|
2011-01-22 21:09:13 -08:00
|
|
|
=> 'PhabricatorDirectoryCategoryEditController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'category/delete/(?P<id>\d+)/'
|
2011-01-22 21:09:13 -08:00
|
|
|
=> 'PhabricatorDirectoryCategoryDeleteController',
|
|
|
|
),
|
2011-01-22 18:33:00 -08:00
|
|
|
'/file/' => array(
|
|
|
|
'$' => 'PhabricatorFileListController',
|
|
|
|
'upload/$' => 'PhabricatorFileUploadController',
|
2011-05-22 11:55:10 -07:00
|
|
|
'dropupload/$' => 'PhabricatorFileDropUploadController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'(?P<view>info)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
|
|
|
|
'(?P<view>view)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
|
|
|
|
'(?P<view>download)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
|
2011-08-16 14:39:01 -07:00
|
|
|
'alt/(?P<key>[^/]+)/(?P<phid>[^/]+)/'
|
|
|
|
=> 'PhabricatorFileAltViewController',
|
2011-05-03 10:45:45 -07:00
|
|
|
'macro/' => array(
|
|
|
|
'$' => 'PhabricatorFileMacroListController',
|
|
|
|
'edit/(?:(?P<id>\d+)/)?$' => 'PhabricatorFileMacroEditController',
|
|
|
|
'delete/(?P<id>\d+)/$' => 'PhabricatorFileMacroDeleteController',
|
|
|
|
),
|
2011-05-02 14:20:24 -07:00
|
|
|
'proxy/$' => 'PhabricatorFileProxyController',
|
2011-05-22 14:40:51 -07:00
|
|
|
'xform/(?P<transform>[^/]+)/(?P<phid>[^/]+)/'
|
|
|
|
=> 'PhabricatorFileTransformController',
|
2011-01-22 18:33:00 -08:00
|
|
|
),
|
2011-01-22 21:09:13 -08:00
|
|
|
'/phid/' => array(
|
2011-01-26 09:02:09 -08:00
|
|
|
'$' => 'PhabricatorPHIDLookupController',
|
|
|
|
'list/$' => 'PhabricatorPHIDListController',
|
2011-01-16 13:51:39 -08:00
|
|
|
),
|
2011-01-23 18:09:16 -08:00
|
|
|
'/people/' => array(
|
|
|
|
'$' => 'PhabricatorPeopleListController',
|
Provide an activity log for login and administrative actions
Summary: This isn't complete, but I figured I'd ship it for review while it's still smallish.
Provide an activity log for high-level system actions (logins, admin actions). This basically allows two things to happen:
- The log itself is useful if there are shenanigans.
- Password login can check it and start CAPTCHA'ing users after a few failed attempts.
I'm going to change how the admin stuff works a little bit too, since right now you can make someone an agent, grab their certificate, revert them back to a normal user, and then act on their behalf over Conduit. This is a little silly, I'm going to move "agent" to the create workflow instead. I'll also add a confirm/email step to the administrative password reset flow.
Test Plan: Took various administrative and non-administrative actions, they appeared in the logs. Filtered the logs in a bunch of different ways.
Reviewers: jungejason, tuomaspelkonen, aran
CC:
Differential Revision: 302
2011-05-17 18:42:21 -07:00
|
|
|
'logs/$' => 'PhabricatorPeopleLogsController',
|
2011-07-25 20:32:02 -07:00
|
|
|
'edit/(?:(?P<id>\d+)/(?:(?P<view>\w+)/)?)?$'
|
|
|
|
=> 'PhabricatorPeopleEditController',
|
2011-01-23 18:09:16 -08:00
|
|
|
),
|
2011-06-18 05:13:56 -03:00
|
|
|
'/p/(?P<username>\w+)/(?:(?P<page>\w+)/)?$'
|
|
|
|
=> 'PhabricatorPeopleProfileController',
|
2011-01-24 09:00:29 -08:00
|
|
|
'/conduit/' => array(
|
|
|
|
'$' => 'PhabricatorConduitConsoleController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'method/(?P<method>[^/]+)$' => 'PhabricatorConduitConsoleController',
|
2011-01-24 09:00:29 -08:00
|
|
|
'log/$' => 'PhabricatorConduitLogController',
|
2011-11-30 15:17:37 -08:00
|
|
|
'log/view/(?P<view>[^/]+)/$' => 'PhabricatorConduitLogController',
|
2011-06-14 12:17:14 -07:00
|
|
|
'token/$' => 'PhabricatorConduitTokenController',
|
2011-01-24 09:00:29 -08:00
|
|
|
),
|
2011-02-07 20:56:27 -08:00
|
|
|
'/api/(?P<method>[^/]+)$' => 'PhabricatorConduitAPIController',
|
2011-01-24 13:18:41 -08:00
|
|
|
|
2011-02-07 20:56:27 -08:00
|
|
|
'/D(?P<id>\d+)' => 'DifferentialRevisionViewController',
|
2011-01-24 13:18:41 -08:00
|
|
|
'/differential/' => array(
|
2011-01-25 15:19:06 -08:00
|
|
|
'$' => 'DifferentialRevisionListController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'filter/(?P<filter>\w+)/$' => 'DifferentialRevisionListController',
|
2011-02-05 12:20:18 -08:00
|
|
|
'diff/' => array(
|
2011-02-07 20:56:27 -08:00
|
|
|
'(?P<id>\d+)/$' => 'DifferentialDiffViewController',
|
2011-02-05 12:20:18 -08:00
|
|
|
'create/$' => 'DifferentialDiffCreateController',
|
|
|
|
),
|
2011-01-31 20:38:13 -08:00
|
|
|
'changeset/$' => 'DifferentialChangesetViewController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'revision/edit/(?:(?P<id>\d+)/)?$'
|
2011-01-25 13:26:09 -08:00
|
|
|
=> 'DifferentialRevisionEditController',
|
2011-01-30 12:08:40 -08:00
|
|
|
'comment/' => array(
|
2011-02-07 20:56:27 -08:00
|
|
|
'preview/(?P<id>\d+)/$' => 'DifferentialCommentPreviewController',
|
2011-01-30 12:08:40 -08:00
|
|
|
'save/$' => 'DifferentialCommentSaveController',
|
|
|
|
'inline/' => array(
|
2011-02-07 20:56:27 -08:00
|
|
|
'preview/(?P<id>\d+)/$' =>
|
2011-02-02 19:38:43 -08:00
|
|
|
'DifferentialInlineCommentPreviewController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'edit/(?P<id>\d+)/$' => 'DifferentialInlineCommentEditController',
|
2011-01-30 12:08:40 -08:00
|
|
|
),
|
|
|
|
),
|
2011-02-19 14:36:13 -08:00
|
|
|
'subscribe/(?P<action>add|rem)/(?P<id>\d+)/$'
|
|
|
|
=> 'DifferentialSubscribeController',
|
2011-01-24 13:18:41 -08:00
|
|
|
),
|
|
|
|
|
2011-01-25 13:48:05 -08:00
|
|
|
'/typeahead/' => array(
|
2011-02-07 20:56:27 -08:00
|
|
|
'common/(?P<type>\w+)/$'
|
2011-01-25 13:48:05 -08:00
|
|
|
=> 'PhabricatorTypeaheadCommonDatasourceController',
|
|
|
|
),
|
2011-01-25 17:40:21 -08:00
|
|
|
|
|
|
|
'/mail/' => array(
|
|
|
|
'$' => 'PhabricatorMetaMTAListController',
|
|
|
|
'send/$' => 'PhabricatorMetaMTASendController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'view/(?P<id>\d+)/$' => 'PhabricatorMetaMTAViewController',
|
2011-01-26 10:40:38 -08:00
|
|
|
'lists/$' => 'PhabricatorMetaMTAMailingListsController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'lists/edit/(?:(?P<id>\d+)/)?$'
|
2011-01-26 10:40:38 -08:00
|
|
|
=> 'PhabricatorMetaMTAMailingListEditController',
|
2011-05-04 23:09:42 -07:00
|
|
|
'receive/$' => 'PhabricatorMetaMTAReceiveController',
|
|
|
|
'received/$' => 'PhabricatorMetaMTAReceivedListController',
|
2011-05-30 11:07:05 -07:00
|
|
|
'sendgrid/$' => 'PhabricatorMetaMTASendGridReceiveController',
|
2011-01-26 10:40:38 -08:00
|
|
|
),
|
2011-01-26 13:21:12 -08:00
|
|
|
|
2011-01-31 11:55:26 -08:00
|
|
|
'/login/' => array(
|
|
|
|
'$' => 'PhabricatorLoginController',
|
|
|
|
'email/$' => 'PhabricatorEmailLoginController',
|
2011-02-07 20:56:27 -08:00
|
|
|
'etoken/(?P<token>\w+)/$' => 'PhabricatorEmailTokenController',
|
Fix conservative CSRF token cycling limit
Summary:
We currently cycle CSRF tokens every hour and check for the last two valid ones.
This means that a form could go stale in as little as an hour, and is certainly
stale after two.
When a stale form is submitted, you basically get a terrible heisen-state where
some of your data might persist if you're lucky but more likely it all just
vanishes. The .js file below outlines some more details.
This is a pretty terrible UX and we don't need to be as conservative about CSRF
validation as we're being. Remedy this problem by:
- Accepting the last 6 CSRF tokens instead of the last 1 (i.e., pages are
valid for at least 6 hours, and for as long as 7).
- Using JS to refresh the CSRF token every 55 minutes (i.e., pages connected
to the internet are valid indefinitely).
- Showing the user an explicit message about what went wrong when CSRF
validation fails so the experience is less bewildering.
They should now only be able to submit with a bad CSRF token if:
- They load a page, disconnect from the internet for 7 hours, reconnect, and
submit the form within 55 minutes; or
- They are actually the victim of a CSRF attack.
We could eventually fix the first one by tracking reconnects, which might be
"free" once the notification server gets built. It will probably never be an
issue in practice.
Test Plan:
- Reduced CSRF cycle frequency to 2 seconds, submitted a form after 15
seconds, got the CSRF exception.
- Reduced csrf-refresh cycle frequency to 3 seconds, submitted a form after 15
seconds, got a clean form post.
- Added debugging code the the csrf refresh to make sure it was doing sensible
things (pulling different tokens, finding all the inputs).
Reviewed By: aran
Reviewers: tuomaspelkonen, jungejason, aran
CC: aran, epriestley
Differential Revision: 660
2011-07-13 14:05:18 -07:00
|
|
|
'refresh/$' => 'PhabricatorRefreshCSRFController',
|
2011-01-31 11:55:26 -08:00
|
|
|
),
|
2011-02-24 14:52:57 -08:00
|
|
|
|
2011-01-30 21:28:45 -08:00
|
|
|
'/logout/$' => 'PhabricatorLogoutController',
|
2011-02-02 13:48:52 -08:00
|
|
|
|
2011-02-20 22:47:56 -08:00
|
|
|
'/oauth/' => array(
|
Add Google as an OAuth2 provider (BETA)
Summary:
This is pretty straightforward, except:
- We need to request read/write access to the address book to get the account
ID (which we MUST have) and real name, email and account name (which we'd like
to have). This is way more access than we should need, but there's apparently no
"get_loggedin_user_basic_information" type of call in the Google API suite (or,
at least, I couldn't find one).
- We can't get the profile picture or profile URI since there's no Plus API
access and Google users don't have meaningful public pages otherwise.
- Google doesn't save the fact that you've authorized the app, so every time
you want to login you need to reaffirm that you want to give us silly amounts of
access. Phabricator sessions are pretty long-duration though so this shouldn't
be a major issue.
Test Plan:
- Registered, logged out, and logged in with Google.
- Registered, logged out, and logged in with Facebook / Github to make sure I
didn't break anything.
- Linked / unlinked Google accounts.
Reviewers: Makinde, jungejason, nh, tuomaspelkonen, aran
Reviewed By: aran
CC: aran, epriestley, Makinde
Differential Revision: 916
2011-09-08 16:37:22 -07:00
|
|
|
'(?P<provider>\w+)/' => array(
|
2011-02-20 22:47:56 -08:00
|
|
|
'login/$' => 'PhabricatorOAuthLoginController',
|
|
|
|
'diagnose/$' => 'PhabricatorOAuthDiagnosticsController',
|
2011-02-21 22:51:34 -08:00
|
|
|
'unlink/$' => 'PhabricatorOAuthUnlinkController',
|
2011-02-20 22:47:56 -08:00
|
|
|
),
|
|
|
|
),
|
|
|
|
|
2011-02-02 13:48:52 -08:00
|
|
|
'/xhprof/' => array(
|
2011-02-07 20:56:27 -08:00
|
|
|
'profile/(?P<phid>[^/]+)/$' => 'PhabricatorXHProfProfileController',
|
2011-02-02 13:48:52 -08:00
|
|
|
),
|
2011-02-02 22:38:42 -08:00
|
|
|
|
|
|
|
'/~/' => 'DarkConsoleController',
|
2011-02-05 22:36:21 -08:00
|
|
|
|
|
|
|
'/settings/' => array(
|
2011-02-07 20:56:27 -08:00
|
|
|
'(?:page/(?P<page>[^/]+)/)?$' => 'PhabricatorUserSettingsController',
|
2011-02-05 22:36:21 -08:00
|
|
|
),
|
2011-02-08 10:53:59 -08:00
|
|
|
|
|
|
|
'/maniphest/' => array(
|
|
|
|
'$' => 'ManiphestTaskListController',
|
|
|
|
'view/(?P<view>\w+)/$' => 'ManiphestTaskListController',
|
|
|
|
'task/' => array(
|
2011-02-20 14:15:53 -08:00
|
|
|
'create/$' => 'ManiphestTaskEditController',
|
|
|
|
'edit/(?P<id>\d+)/$' => 'ManiphestTaskEditController',
|
2011-05-20 18:56:18 -07:00
|
|
|
'descriptionchange/(?P<id>\d+)/$' =>
|
|
|
|
'ManiphestTaskDescriptionChangeController',
|
2011-02-08 10:53:59 -08:00
|
|
|
),
|
|
|
|
'transaction/' => array(
|
|
|
|
'save/' => 'ManiphestTransactionSaveController',
|
2011-05-10 08:29:28 -07:00
|
|
|
'preview/(?P<id>\d+)/$' => 'ManiphestTransactionPreviewController',
|
2011-02-08 10:53:59 -08:00
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
'/T(?P<id>\d+)$' => 'ManiphestTaskDetailController',
|
2011-02-12 18:26:15 -08:00
|
|
|
|
|
|
|
'/github-post-receive/(?P<id>\d+)/(?P<token>[^/]+)/$'
|
|
|
|
=> 'PhabricatorRepositoryGitHubPostReceiveController',
|
2011-02-19 14:36:13 -08:00
|
|
|
|
2011-02-12 18:26:15 -08:00
|
|
|
'/repository/' => array(
|
|
|
|
'$' => 'PhabricatorRepositoryListController',
|
|
|
|
'create/$' => 'PhabricatorRepositoryCreateController',
|
2011-03-06 22:29:22 -08:00
|
|
|
'edit/(?P<id>\d+)/(?:(?P<view>\w+)?/)?$' =>
|
|
|
|
'PhabricatorRepositoryEditController',
|
2011-02-12 18:26:15 -08:00
|
|
|
'delete/(?P<id>\d+)/$' => 'PhabricatorRepositoryDeleteController',
|
2011-04-05 20:49:31 -07:00
|
|
|
'project/(?P<id>\d+)/' =>
|
|
|
|
'PhabricatorRepositoryArcanistProjectEditController',
|
2011-02-12 18:26:15 -08:00
|
|
|
),
|
2011-02-14 15:34:20 -08:00
|
|
|
|
|
|
|
'/search/' => array(
|
|
|
|
'$' => 'PhabricatorSearchController',
|
|
|
|
'(?P<id>\d+)/$' => 'PhabricatorSearchController',
|
2011-06-14 07:55:04 -07:00
|
|
|
'attach/(?P<phid>[^/]+)/(?P<type>\w+)/(?:(?P<action>\w+)/)?$'
|
2011-05-16 11:43:39 -07:00
|
|
|
=> 'PhabricatorSearchAttachController',
|
|
|
|
'select/(?P<type>\w+)/$'
|
|
|
|
=> 'PhabricatorSearchSelectController',
|
2011-06-15 07:43:43 -07:00
|
|
|
'index/(?P<phid>[^/]+)/$' => 'PhabricatorSearchIndexController',
|
2011-02-14 15:34:20 -08:00
|
|
|
),
|
2011-02-20 18:41:23 -08:00
|
|
|
|
|
|
|
'/project/' => array(
|
|
|
|
'$' => 'PhabricatorProjectListController',
|
2011-06-26 08:37:47 -07:00
|
|
|
'edit/(?P<id>\d+)/$' => 'PhabricatorProjectProfileEditController',
|
2011-06-18 05:13:56 -03:00
|
|
|
'view/(?P<id>\d+)/(?:(?P<page>\w+)/)?$'
|
|
|
|
=> 'PhabricatorProjectProfileController',
|
2011-02-20 18:41:23 -08:00
|
|
|
'affiliation/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorProjectAffiliationEditController',
|
2011-06-26 08:37:47 -07:00
|
|
|
'create/$' => 'PhabricatorProjectCreateController',
|
2011-02-24 14:52:57 -08:00
|
|
|
),
|
|
|
|
|
2011-03-11 09:34:22 -08:00
|
|
|
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$'
|
|
|
|
=> 'DiffusionCommitController',
|
2011-03-07 15:13:36 -08:00
|
|
|
'/diffusion/' => array(
|
|
|
|
'$' => 'DiffusionHomeController',
|
2011-03-12 16:17:34 -08:00
|
|
|
'(?P<callsign>[A-Z]+)/' => array(
|
|
|
|
'$' => 'DiffusionRepositoryController',
|
2011-03-31 01:07:51 -07:00
|
|
|
'repository/'.
|
|
|
|
'(?P<path>[^/]+)/'.
|
|
|
|
'$'
|
|
|
|
=> 'DiffusionRepositoryController',
|
2011-03-13 22:03:30 -07:00
|
|
|
'change/'.
|
|
|
|
'(?P<path>.*?)'.
|
|
|
|
'(?:[;](?P<commit>[a-z0-9]+))?'.
|
|
|
|
'$'
|
|
|
|
=> 'DiffusionChangeController',
|
2011-03-12 16:17:34 -08:00
|
|
|
'history/'.
|
2011-03-08 17:31:44 -08:00
|
|
|
'(?P<path>.*?)'.
|
|
|
|
'(?:[;](?P<commit>[a-z0-9]+))?'.
|
|
|
|
'$'
|
|
|
|
=> 'DiffusionHistoryController',
|
2011-03-12 16:17:34 -08:00
|
|
|
'browse/'.
|
2011-03-08 17:31:44 -08:00
|
|
|
'(?P<path>.*?)'.
|
|
|
|
'(?:[;](?P<commit>[a-z0-9]+))?'.
|
|
|
|
'(?:[$](?P<line>\d+))?'.
|
|
|
|
'$'
|
|
|
|
=> 'DiffusionBrowseController',
|
2011-03-30 17:36:16 -07:00
|
|
|
'diff/'.
|
|
|
|
'(?P<path>.*?)'.
|
|
|
|
'(?:[;](?P<commit>[a-z0-9]+))?'.
|
|
|
|
'$'
|
|
|
|
=> 'DiffusionDiffController',
|
2011-03-30 23:27:06 -07:00
|
|
|
'lastmodified/'.
|
|
|
|
'(?P<path>.*?)'.
|
|
|
|
'(?:[;](?P<commit>[a-z0-9]+))?'.
|
|
|
|
'$'
|
|
|
|
=> 'DiffusionLastModifiedController',
|
2011-03-08 17:31:44 -08:00
|
|
|
),
|
2011-04-03 19:20:47 -07:00
|
|
|
'services/' => array(
|
|
|
|
'path/' => array(
|
|
|
|
'complete/$' => 'DiffusionPathCompleteController',
|
|
|
|
'validate/$' => 'DiffusionPathValidateController',
|
|
|
|
),
|
|
|
|
),
|
2011-07-23 17:09:03 -07:00
|
|
|
'author/' => array(
|
|
|
|
'$' => 'DiffusionCommitListController',
|
|
|
|
'(?P<username>\w+)/$' => 'DiffusionCommitListController',
|
|
|
|
),
|
2011-09-05 10:43:24 -07:00
|
|
|
'symbol/(?P<name>[^/]+)/$' => 'DiffusionSymbolController',
|
2011-03-07 15:13:36 -08:00
|
|
|
),
|
|
|
|
|
2011-03-10 13:48:29 -08:00
|
|
|
'/daemon/' => array(
|
2011-03-26 22:55:18 -07:00
|
|
|
'task/(?P<id>\d+)/$' => 'PhabricatorWorkerTaskDetailController',
|
2011-03-15 13:38:14 -07:00
|
|
|
'log/' => array(
|
2011-05-02 17:05:22 -07:00
|
|
|
'$' => 'PhabricatorDaemonLogListController',
|
|
|
|
'combined/$' => 'PhabricatorDaemonCombinedLogController',
|
2011-03-15 13:38:14 -07:00
|
|
|
'(?P<id>\d+)/$' => 'PhabricatorDaemonLogViewController',
|
|
|
|
),
|
2011-03-11 09:34:22 -08:00
|
|
|
'timeline/$' => 'PhabricatorDaemonTimelineConsoleController',
|
|
|
|
'timeline/(?P<id>\d+)/$' => 'PhabricatorDaemonTimelineEventController',
|
2011-03-10 13:48:29 -08:00
|
|
|
'$' => 'PhabricatorDaemonConsoleController',
|
|
|
|
),
|
|
|
|
|
2011-03-22 13:49:46 -07:00
|
|
|
'/herald/' => array(
|
|
|
|
'$' => 'HeraldHomeController',
|
|
|
|
'view/(?P<view>[^/]+)/$' => 'HeraldHomeController',
|
2011-03-22 14:34:38 -07:00
|
|
|
'new/(?:(?P<type>[^/]+)/)?$' => 'HeraldNewController',
|
2011-04-03 23:45:27 -07:00
|
|
|
'rule/(?:(?P<id>\d+)/)?$' => 'HeraldRuleController',
|
2011-03-24 11:07:36 -07:00
|
|
|
'delete/(?P<id>\d+)/$' => 'HeraldDeleteController',
|
2011-03-24 13:49:21 -07:00
|
|
|
'test/$' => 'HeraldTestConsoleController',
|
2011-11-06 01:07:04 -07:00
|
|
|
'all/' => array(
|
|
|
|
'$' => 'HeraldAllRulesController',
|
|
|
|
'view/(?P<view>[^/]+)/$' => 'HeraldAllRulesController',
|
|
|
|
),
|
2011-03-24 13:49:21 -07:00
|
|
|
'transcript/$' => 'HeraldTranscriptListController',
|
2011-03-24 21:32:26 -07:00
|
|
|
'transcript/(?P<id>\d+)/(?:(?P<filter>\w+)/)?$'
|
|
|
|
=> 'HeraldTranscriptController',
|
2011-03-22 13:49:46 -07:00
|
|
|
),
|
|
|
|
|
2011-03-31 17:06:33 -07:00
|
|
|
'/uiexample/' => array(
|
|
|
|
'$' => 'PhabricatorUIExampleRenderController',
|
|
|
|
'view/(?P<class>[^/]+)/$' => 'PhabricatorUIExampleRenderController',
|
|
|
|
),
|
|
|
|
|
2011-04-03 14:48:36 -07:00
|
|
|
'/owners/' => array(
|
|
|
|
'$' => 'PhabricatorOwnersListController',
|
|
|
|
'view/(?P<view>[^/]+)/$' => 'PhabricatorOwnersListController',
|
2011-04-03 22:03:27 -07:00
|
|
|
'edit/(?P<id>\d+)/$' => 'PhabricatorOwnersEditController',
|
|
|
|
'new/$' => 'PhabricatorOwnersEditController',
|
2011-04-03 14:48:36 -07:00
|
|
|
'package/(?P<id>\d+)/$' => 'PhabricatorOwnersDetailController',
|
2011-04-03 22:03:27 -07:00
|
|
|
'delete/(?P<id>\d+)/$' => 'PhabricatorOwnersDeleteController',
|
2011-04-03 14:48:36 -07:00
|
|
|
),
|
|
|
|
|
2011-04-06 19:17:05 -07:00
|
|
|
'/xhpast/' => array(
|
|
|
|
'$' => 'PhabricatorXHPASTViewRunController',
|
|
|
|
'view/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorXHPASTViewFrameController',
|
|
|
|
'frameset/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorXHPASTViewFramesetController',
|
|
|
|
'input/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorXHPASTViewInputController',
|
|
|
|
'tree/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorXHPASTViewTreeController',
|
|
|
|
'stream/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorXHPASTViewStreamController',
|
|
|
|
),
|
|
|
|
|
2011-04-08 11:13:29 -07:00
|
|
|
'/status/$' => 'PhabricatorStatusController',
|
|
|
|
|
2011-06-10 02:53:53 -04:00
|
|
|
'/paste/' => array(
|
2011-12-13 09:48:17 -08:00
|
|
|
'$' => 'PhabricatorPasteListController',
|
|
|
|
'filter/(?P<filter>\w+)/$' => 'PhabricatorPasteListController',
|
2011-06-10 02:53:53 -04:00
|
|
|
),
|
|
|
|
'/P(?P<id>\d+)$' => 'PhabricatorPasteViewController',
|
|
|
|
|
2011-05-28 11:36:00 -07:00
|
|
|
'/help/' => array(
|
|
|
|
'keyboardshortcut/$' => 'PhabricatorHelpKeyboardShortcutController',
|
|
|
|
),
|
2011-06-12 23:06:17 +00:00
|
|
|
|
|
|
|
'/countdown/' => array(
|
|
|
|
'$'
|
|
|
|
=> 'PhabricatorCountdownListController',
|
|
|
|
'(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorCountdownViewController',
|
|
|
|
'edit/(?:(?P<id>\d+)/)?$'
|
|
|
|
=> 'PhabricatorCountdownEditController',
|
|
|
|
'delete/(?P<id>\d+)/$'
|
|
|
|
=> 'PhabricatorCountdownDeleteController'
|
|
|
|
),
|
2011-07-05 08:35:18 -07:00
|
|
|
|
|
|
|
'/feed/' => array(
|
|
|
|
'$' => 'PhabricatorFeedStreamController',
|
2011-07-09 18:03:59 -07:00
|
|
|
'public/$' => 'PhabricatorFeedPublicStreamController',
|
2011-07-05 08:35:18 -07:00
|
|
|
),
|
2011-07-08 11:13:11 -07:00
|
|
|
|
|
|
|
'/V(?P<id>\d+)$' => 'PhabricatorSlowvotePollController',
|
|
|
|
'/vote/' => array(
|
|
|
|
'(?:view/(?P<view>\w+)/)?$' => 'PhabricatorSlowvoteListController',
|
|
|
|
'create/' => 'PhabricatorSlowvoteCreateController',
|
|
|
|
),
|
2011-07-11 08:54:22 -07:00
|
|
|
|
|
|
|
// Match "/w/" with slug "/".
|
|
|
|
'/w(?P<slug>/)$' => 'PhrictionDocumentController',
|
|
|
|
// Match "/w/x/y/z/" with slug "x/y/z/".
|
|
|
|
'/w/(?P<slug>.+/)$' => 'PhrictionDocumentController',
|
2011-07-11 12:34:53 -07:00
|
|
|
|
|
|
|
'/phriction/' => array(
|
2011-07-11 15:42:12 -07:00
|
|
|
'$' => 'PhrictionListController',
|
|
|
|
'list/(?P<view>[^/]+)/$' => 'PhrictionListController',
|
|
|
|
|
2011-07-11 15:06:19 -07:00
|
|
|
'history(?P<slug>/)$' => 'PhrictionHistoryController',
|
|
|
|
'history/(?P<slug>.+/)$' => 'PhrictionHistoryController',
|
|
|
|
|
2011-07-11 12:34:53 -07:00
|
|
|
'edit/(?:(?P<id>\d+)/)?$' => 'PhrictionEditController',
|
2011-07-16 18:25:45 -07:00
|
|
|
|
|
|
|
'preview/$' => 'PhrictionDocumentPreviewController',
|
2011-07-17 11:06:02 -07:00
|
|
|
'diff/(?P<id>\d+)/$' => 'PhrictionDiffController',
|
2011-07-11 12:34:53 -07:00
|
|
|
),
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-07 18:26:31 -07:00
|
|
|
|
|
|
|
'/calendar/' => array(
|
|
|
|
'$' => 'PhabricatorCalendarBrowseController',
|
|
|
|
),
|
2011-02-24 14:52:57 -08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getResourceURIMapRules() {
|
|
|
|
return array(
|
|
|
|
'/res/' => array(
|
|
|
|
'(?P<package>pkg/)?(?P<hash>[a-f0-9]{8})/(?P<path>.+\.(?:css|js))$'
|
|
|
|
=> 'CelerityResourceController',
|
|
|
|
),
|
2011-01-16 13:51:39 -08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function buildRequest() {
|
|
|
|
$request = new AphrontRequest($this->getHost(), $this->getPath());
|
|
|
|
$request->setRequestData($_GET + $_POST);
|
2011-02-02 13:48:52 -08:00
|
|
|
$request->setApplicationConfiguration($this);
|
2011-01-16 13:51:39 -08:00
|
|
|
return $request;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function handleException(Exception $ex) {
|
|
|
|
|
2011-05-09 01:10:40 -07:00
|
|
|
// Always log the unhandled exception.
|
|
|
|
phlog($ex);
|
|
|
|
|
2011-01-16 13:51:39 -08:00
|
|
|
$class = phutil_escape_html(get_class($ex));
|
|
|
|
$message = phutil_escape_html($ex->getMessage());
|
|
|
|
|
2011-08-17 14:29:53 -07:00
|
|
|
if (PhabricatorEnv::getEnvConfig('phabricator.show-stack-traces')) {
|
|
|
|
$trace = $this->renderStackTrace($ex->getTrace());
|
|
|
|
} else {
|
|
|
|
$trace = null;
|
|
|
|
}
|
2011-07-07 12:49:59 -07:00
|
|
|
|
2011-01-16 13:51:39 -08:00
|
|
|
$content =
|
|
|
|
'<div class="aphront-unhandled-exception">'.
|
2011-08-17 14:29:53 -07:00
|
|
|
'<div class="exception-message">'.$message.'</div>'.
|
|
|
|
$trace.
|
2011-01-16 13:51:39 -08:00
|
|
|
'</div>';
|
|
|
|
|
2011-02-26 20:57:21 -08:00
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
if (!$user) {
|
|
|
|
// If we hit an exception very early, we won't have a user.
|
|
|
|
$user = new PhabricatorUser();
|
2011-02-17 14:32:01 -08:00
|
|
|
}
|
|
|
|
|
2011-02-26 20:57:21 -08:00
|
|
|
$dialog = new AphrontDialogView();
|
|
|
|
$dialog
|
2011-08-17 14:29:53 -07:00
|
|
|
->setTitle('Unhandled Exception ("'.$class.'")')
|
2011-02-26 20:57:21 -08:00
|
|
|
->setClass('aphront-exception-dialog')
|
|
|
|
->setUser($user)
|
2011-08-17 14:29:53 -07:00
|
|
|
->appendChild($content);
|
|
|
|
|
|
|
|
if ($this->getRequest()->isAjax()) {
|
|
|
|
$dialog->addCancelButton('/', 'Close');
|
|
|
|
}
|
2011-01-16 13:51:39 -08:00
|
|
|
|
2011-02-26 20:57:21 -08:00
|
|
|
$response = new AphrontDialogResponse();
|
|
|
|
$response->setDialog($dialog);
|
2011-01-16 13:51:39 -08:00
|
|
|
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function willSendResponse(AphrontResponse $response) {
|
|
|
|
$request = $this->getRequest();
|
2011-05-16 11:43:39 -07:00
|
|
|
$response->setRequest($request);
|
2011-01-16 13:51:39 -08:00
|
|
|
if ($response instanceof AphrontDialogResponse) {
|
|
|
|
if (!$request->isAjax()) {
|
2011-01-22 17:48:55 -08:00
|
|
|
$view = new PhabricatorStandardPageView();
|
2011-02-04 17:53:14 -08:00
|
|
|
$view->setRequest($request);
|
2011-01-16 13:51:39 -08:00
|
|
|
$view->appendChild(
|
|
|
|
'<div style="padding: 2em 0;">'.
|
|
|
|
$response->buildResponseString().
|
|
|
|
'</div>');
|
|
|
|
$response = new AphrontWebpageResponse();
|
|
|
|
$response->setContent($view->render());
|
|
|
|
return $response;
|
2011-02-01 16:42:36 -08:00
|
|
|
} else {
|
|
|
|
return id(new AphrontAjaxResponse())
|
|
|
|
->setContent(array(
|
|
|
|
'dialog' => $response->buildResponseString(),
|
|
|
|
));
|
2011-01-16 13:51:39 -08:00
|
|
|
}
|
2011-02-05 11:45:13 -08:00
|
|
|
} else if ($response instanceof AphrontRedirectResponse) {
|
|
|
|
if ($request->isAjax()) {
|
|
|
|
return id(new AphrontAjaxResponse())
|
|
|
|
->setContent(
|
|
|
|
array(
|
|
|
|
'redirect' => $response->getURI(),
|
|
|
|
));
|
|
|
|
}
|
2011-01-30 08:44:28 -08:00
|
|
|
} else if ($response instanceof Aphront404Response) {
|
2011-01-30 09:15:01 -08:00
|
|
|
|
|
|
|
$failure = new AphrontRequestFailureView();
|
|
|
|
$failure->setHeader('404 Not Found');
|
|
|
|
$failure->appendChild(
|
|
|
|
'<p>The page you requested was not found.</p>');
|
|
|
|
|
2011-01-30 08:44:28 -08:00
|
|
|
$view = new PhabricatorStandardPageView();
|
|
|
|
$view->setTitle('404 Not Found');
|
2011-02-02 13:48:52 -08:00
|
|
|
$view->setRequest($this->getRequest());
|
2011-01-30 09:15:01 -08:00
|
|
|
$view->appendChild($failure);
|
|
|
|
|
2011-01-30 08:44:28 -08:00
|
|
|
$response = new AphrontWebpageResponse();
|
|
|
|
$response->setContent($view->render());
|
|
|
|
$response->setHTTPResponseCode(404);
|
|
|
|
return $response;
|
2011-01-16 13:51:39 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
2011-01-29 16:16:09 -08:00
|
|
|
public function build404Controller() {
|
2011-01-30 08:44:28 -08:00
|
|
|
return array(new Phabricator404Controller($this->getRequest()), array());
|
2011-01-29 16:16:09 -08:00
|
|
|
}
|
|
|
|
|
2011-04-04 10:29:46 -07:00
|
|
|
public function buildRedirectController($uri) {
|
|
|
|
return array(
|
|
|
|
new PhabricatorRedirectController($this->getRequest()),
|
|
|
|
array(
|
|
|
|
'uri' => $uri,
|
|
|
|
));
|
|
|
|
}
|
2011-01-16 13:51:39 -08:00
|
|
|
|
2011-08-17 14:29:53 -07:00
|
|
|
private function renderStackTrace($trace) {
|
|
|
|
|
|
|
|
$libraries = PhutilBootloader::getInstance()->getAllLibraries();
|
|
|
|
|
|
|
|
// TODO: Make this configurable?
|
|
|
|
$host = 'https://secure.phabricator.com';
|
|
|
|
|
|
|
|
$browse = array(
|
|
|
|
'arcanist' =>
|
|
|
|
$host.'/diffusion/ARC/browse/origin:master/src/',
|
|
|
|
'phutil' =>
|
|
|
|
$host.'/diffusion/PHU/browse/origin:master/src/',
|
|
|
|
'phabricator' =>
|
|
|
|
$host.'/diffusion/P/browse/origin:master/src/',
|
|
|
|
);
|
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
$depth = count($trace);
|
|
|
|
foreach ($trace as $part) {
|
|
|
|
$lib = null;
|
2011-08-21 13:07:09 -07:00
|
|
|
$file = idx($part, 'file');
|
2011-08-17 14:29:53 -07:00
|
|
|
$relative = $file;
|
|
|
|
foreach ($libraries as $library) {
|
|
|
|
$root = phutil_get_library_root($library);
|
|
|
|
if (Filesystem::isDescendant($file, $root)) {
|
|
|
|
$lib = $library;
|
|
|
|
$relative = Filesystem::readablePath($file, $root);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$where = '';
|
|
|
|
if (isset($part['class'])) {
|
|
|
|
$where .= $part['class'].'::';
|
|
|
|
}
|
|
|
|
if (isset($part['function'])) {
|
|
|
|
$where .= $part['function'].'()';
|
|
|
|
}
|
|
|
|
|
2011-08-21 13:07:09 -07:00
|
|
|
if ($file) {
|
|
|
|
if (isset($browse[$lib])) {
|
|
|
|
$file_name = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $browse[$lib].$relative.'$'.$part['line'],
|
|
|
|
'title' => $file,
|
|
|
|
'target' => '_blank',
|
|
|
|
),
|
|
|
|
phutil_escape_html($relative));
|
|
|
|
} else {
|
|
|
|
$file_name = phutil_render_tag(
|
|
|
|
'span',
|
|
|
|
array(
|
|
|
|
'title' => $file,
|
|
|
|
),
|
|
|
|
phutil_escape_html($relative));
|
|
|
|
}
|
|
|
|
$file_name = $file_name.' : '.(int)$part['line'];
|
2011-08-17 14:29:53 -07:00
|
|
|
} else {
|
2011-08-21 13:07:09 -07:00
|
|
|
$file_name = '<em>(Internal)</em>';
|
2011-08-17 14:29:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$rows[] = array(
|
|
|
|
$depth--,
|
|
|
|
phutil_escape_html($lib),
|
|
|
|
$file_name,
|
|
|
|
phutil_escape_html($where),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
$table = new AphrontTableView($rows);
|
|
|
|
$table->setHeaders(
|
|
|
|
array(
|
|
|
|
'Depth',
|
|
|
|
'Library',
|
|
|
|
'File',
|
|
|
|
'Where',
|
|
|
|
));
|
|
|
|
$table->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'n',
|
|
|
|
'',
|
|
|
|
'',
|
|
|
|
'wide',
|
|
|
|
));
|
|
|
|
|
|
|
|
return
|
|
|
|
'<div class="exception-trace">'.
|
|
|
|
'<div class="exception-trace-header">Stack Trace</div>'.
|
|
|
|
$table->render().
|
|
|
|
'</div>';
|
|
|
|
}
|
|
|
|
|
2011-01-16 13:51:39 -08:00
|
|
|
}
|