diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -5222,6 +5222,7 @@ 'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php', 'PhortuneAccountBillingAddressTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingAddressTransaction.php', 'PhortuneAccountBillingNameTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingNameTransaction.php', + 'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php', 'PhortuneAccountChargesController' => 'applications/phortune/controller/account/PhortuneAccountChargesController.php', 'PhortuneAccountController' => 'applications/phortune/controller/account/PhortuneAccountController.php', 'PhortuneAccountDetailsController' => 'applications/phortune/controller/account/PhortuneAccountDetailsController.php', @@ -5246,6 +5247,7 @@ 'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php', 'PhortuneAccountManagersController' => 'applications/phortune/controller/account/PhortuneAccountManagersController.php', 'PhortuneAccountNameTransaction' => 'applications/phortune/xaction/PhortuneAccountNameTransaction.php', + 'PhortuneAccountOrderListController' => 'applications/phortune/controller/account/PhortuneAccountOrderListController.php', 'PhortuneAccountOrdersController' => 'applications/phortune/controller/account/PhortuneAccountOrdersController.php', 'PhortuneAccountOverviewController' => 'applications/phortune/controller/account/PhortuneAccountOverviewController.php', 'PhortuneAccountPHIDType' => 'applications/phortune/phid/PhortuneAccountPHIDType.php', @@ -5279,7 +5281,6 @@ 'PhortuneCartUpdateController' => 'applications/phortune/controller/cart/PhortuneCartUpdateController.php', 'PhortuneCartViewController' => 'applications/phortune/controller/cart/PhortuneCartViewController.php', 'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php', - 'PhortuneChargeListController' => 'applications/phortune/controller/charge/PhortuneChargeListController.php', 'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php', 'PhortuneChargeQuery' => 'applications/phortune/query/PhortuneChargeQuery.php', 'PhortuneChargeSearchEngine' => 'applications/phortune/query/PhortuneChargeSearchEngine.php', @@ -11787,6 +11788,7 @@ 'PhortuneAccountAddManagerController' => 'PhortuneAccountController', 'PhortuneAccountBillingAddressTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountBillingNameTransaction' => 'PhortuneAccountTransactionType', + 'PhortuneAccountChargeListController' => 'PhortuneAccountProfileController', 'PhortuneAccountChargesController' => 'PhortuneAccountProfileController', 'PhortuneAccountController' => 'PhortuneController', 'PhortuneAccountDetailsController' => 'PhortuneAccountProfileController', @@ -11816,6 +11818,7 @@ 'PhortuneAccountListController' => 'PhortuneController', 'PhortuneAccountManagersController' => 'PhortuneAccountProfileController', 'PhortuneAccountNameTransaction' => 'PhortuneAccountTransactionType', + 'PhortuneAccountOrderListController' => 'PhortuneAccountProfileController', 'PhortuneAccountOrdersController' => 'PhortuneAccountProfileController', 'PhortuneAccountOverviewController' => 'PhortuneAccountProfileController', 'PhortuneAccountPHIDType' => 'PhabricatorPHIDType', @@ -11836,6 +11839,7 @@ 'PhortuneDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', + 'PhabricatorExtendedPolicyInterface', ), 'PhortuneCartAcceptController' => 'PhortuneCartController', 'PhortuneCartCancelController' => 'PhortuneCartController', @@ -11855,8 +11859,8 @@ 'PhortuneCharge' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', + 'PhabricatorExtendedPolicyInterface', ), - 'PhortuneChargeListController' => 'PhortuneController', 'PhortuneChargePHIDType' => 'PhabricatorPHIDType', 'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine', diff --git a/src/applications/phortune/application/PhabricatorPhortuneApplication.php b/src/applications/phortune/application/PhabricatorPhortuneApplication.php --- a/src/applications/phortune/application/PhabricatorPhortuneApplication.php +++ b/src/applications/phortune/application/PhabricatorPhortuneApplication.php @@ -34,24 +34,6 @@ return array( '/phortune/' => array( '' => 'PhortuneLandingController', - '(?P\d+)/' => array( - '' => 'PhortuneAccountOverviewController', - 'card/' => array( - 'new/' => 'PhortunePaymentMethodCreateController', - ), - 'subscription/' => array( - '(?:query/(?P[^/]+)/)?' - => 'PhortuneSubscriptionListController', - 'view/(?P\d+)/' - => 'PhortuneAccountSubscriptionViewController', - 'order/(?P\d+)/' - => 'PhortuneCartListController', - ), - 'order/(?:query/(?P[^/]+)/)?' - => 'PhortuneCartListController', - 'charge/(?:query/(?P[^/]+)/)?' - => 'PhortuneChargeListController', - ), 'card/(?P\d+)/' => array( 'edit/' => 'PhortunePaymentMethodEditController', 'disable/' => 'PhortunePaymentMethodDisableController', @@ -65,22 +47,36 @@ ), 'account/' => array( '' => 'PhortuneAccountListController', + $this->getEditRoutePattern('edit/') => 'PhortuneAccountEditController', '(?P\d+)/' => array( + '' => 'PhortuneAccountOverviewController', 'details/' => 'PhortuneAccountDetailsController', 'methods/' => array( '' => 'PhortuneAccountPaymentMethodController', '(?P\d+)/' => 'PhortuneAccountPaymentMethodViewController', + 'new/' => 'PhortunePaymentMethodCreateController', + ), + 'orders/' => array( + '' => 'PhortuneAccountOrdersController', + $this->getQueryRoutePattern('list/') + => 'PhortuneAccountOrderListController', + ), + 'charges/' => array( + '' => 'PhortuneAccountChargesController', + $this->getQueryRoutePattern('list/') + => 'PhortuneAccountChargeListController', ), - 'orders/' => 'PhortuneAccountOrdersController', - 'charges/' => 'PhortuneAccountChargesController', 'subscriptions/' => array( '' => 'PhortuneAccountSubscriptionController', '(?P\d+)/' => array( + '' => 'PhortuneAccountSubscriptionViewController', 'autopay/(?P\d+)/' => 'PhortuneAccountSubscriptionAutopayController', + $this->getQueryRoutePattern('orders/') + => 'PhortuneAccountOrderListController', ), ), 'managers/' => array( diff --git a/src/applications/phortune/controller/account/PhortuneAccountChargeListController.php b/src/applications/phortune/controller/account/PhortuneAccountChargeListController.php new file mode 100644 --- /dev/null +++ b/src/applications/phortune/controller/account/PhortuneAccountChargeListController.php @@ -0,0 +1,35 @@ +getViewer(); + $account = $this->getAccount(); + + return id(new PhortuneChargeSearchEngine()) + ->setAccount($account) + ->setController($this) + ->buildResponse(); + } + + protected function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + + if ($this->hasAccount()) { + $account = $this->getAccount(); + $id = $account->getID(); + + $crumbs->addTextCrumb( + pht('Charges'), + $account->getChargesURI()); + } + + return $crumbs; + } + +} diff --git a/src/applications/phortune/controller/account/PhortuneAccountChargesController.php b/src/applications/phortune/controller/account/PhortuneAccountChargesController.php --- a/src/applications/phortune/controller/account/PhortuneAccountChargesController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountChargesController.php @@ -56,7 +56,7 @@ $handles = $this->loadViewerHandles($phids); - $charges_uri = $this->getApplicationURI($account->getID().'/charge/'); + $charges_uri = $account->getChargeListURI(); $table = id(new PhortuneChargeTableView()) ->setUser($viewer) diff --git a/src/applications/phortune/controller/account/PhortuneAccountController.php b/src/applications/phortune/controller/account/PhortuneAccountController.php --- a/src/applications/phortune/controller/account/PhortuneAccountController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountController.php @@ -23,7 +23,7 @@ abstract protected function shouldRequireAccountEditCapability(); abstract protected function handleAccountRequest(AphrontRequest $request); - private function hasAccount() { + final protected function hasAccount() { return (bool)$this->account; } diff --git a/src/applications/phortune/controller/account/PhortuneAccountOrderListController.php b/src/applications/phortune/controller/account/PhortuneAccountOrderListController.php new file mode 100644 --- /dev/null +++ b/src/applications/phortune/controller/account/PhortuneAccountOrderListController.php @@ -0,0 +1,58 @@ +getViewer(); + $account = $this->getAccount(); + + $engine = id(new PhortuneCartSearchEngine()) + ->setController($this) + ->setAccount($account); + + $subscription_id = $request->getURIData('subscriptionID'); + if ($subscription_id) { + $subscription = id(new PhortuneSubscriptionQuery()) + ->setViewer($viewer) + ->withIDs(array($subscription_id)) + ->executeOne(); + if (!$subscription) { + return new Aphront404Response(); + } + + $engine->setSubscription($subscription); + $this->subscription = $subscription; + } + + return $engine->buildResponse(); + } + + protected function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + + $subscription = $this->subscription; + if ($subscription) { + $crumbs->addTextCrumb( + $subscription->getObjectName(), + $subscription->getURI()); + } else if ($this->hasAccount()) { + $account = $this->getAccount(); + $id = $account->getID(); + + $crumbs->addTextCrumb( + pht('Orders'), + $account->getOrdersURI()); + } + + return $crumbs; + } + + +} diff --git a/src/applications/phortune/controller/account/PhortuneAccountPaymentMethodController.php b/src/applications/phortune/controller/account/PhortuneAccountPaymentMethodController.php --- a/src/applications/phortune/controller/account/PhortuneAccountPaymentMethodController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountPaymentMethodController.php @@ -50,7 +50,7 @@ ->setTag('a') ->setText(pht('Add Payment Method')) ->setIcon('fa-plus') - ->setHref($this->getApplicationURI("{$id}/card/new/")) + ->setHref($this->getApplicationURI("account/{$id}/methods/new/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit); diff --git a/src/applications/phortune/controller/account/PhortuneAccountProfileController.php b/src/applications/phortune/controller/account/PhortuneAccountProfileController.php --- a/src/applications/phortune/controller/account/PhortuneAccountProfileController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountProfileController.php @@ -3,10 +3,6 @@ abstract class PhortuneAccountProfileController extends PhortuneAccountController { - public function buildApplicationMenu() { - return $this->buildSideNavView()->getMenu(); - } - protected function buildHeaderView() { $viewer = $this->getViewer(); $account = $this->getAccount(); @@ -44,7 +40,7 @@ $nav->addFilter( 'overview', pht('Overview'), - $this->getApplicationURI("/{$id}/"), + $account->getURI(), 'fa-user-circle'); $nav->newLink('details') @@ -59,25 +55,25 @@ $nav->addFilter( 'methods', pht('Payment Methods'), - $this->getApplicationURI("/account/{$id}/methods/"), + $account->getPaymentMethodsURI(), 'fa-credit-card'); $nav->addFilter( 'subscriptions', pht('Subscriptions'), - $this->getApplicationURI("/account/{$id}/subscriptions/"), + $account->getSubscriptionsURI(), 'fa-retweet'); $nav->addFilter( 'orders', pht('Order History'), - $this->getApplicationURI("/account/{$id}/orders/"), + $account->getOrdersURI(), 'fa-shopping-bag'); $nav->addFilter( 'charges', pht('Charge History'), - $this->getApplicationURI("/account/{$id}/charges/"), + $account->getChargesURI(), 'fa-calculator'); $nav->addLabel(pht('Personnel')); @@ -90,7 +86,7 @@ $nav->newLink('addresses') ->setname(pht('Email Addresses')) - ->setHref($this->getApplicationURI("/account/{$id}/addresses/")) + ->setHref($account->getEmailAddressesURI()) ->setIcon('fa-envelope-o') ->setWorkflow(!$can_edit) ->setDisabled(!$can_edit); @@ -130,7 +126,7 @@ } $handles = $this->loadViewerHandles($phids); - $orders_uri = $this->getApplicationURI($account->getID().'/order/'); + $orders_uri = $account->getOrderListURI(); $table = id(new PhortuneOrderTableView()) ->setUser($viewer) diff --git a/src/applications/phortune/controller/account/PhortuneAccountSubscriptionViewController.php b/src/applications/phortune/controller/account/PhortuneAccountSubscriptionViewController.php --- a/src/applications/phortune/controller/account/PhortuneAccountSubscriptionViewController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountSubscriptionViewController.php @@ -12,7 +12,7 @@ $subscription = id(new PhortuneSubscriptionQuery()) ->setViewer($viewer) - ->withIDs(array($request->getURIData('id'))) + ->withIDs(array($request->getURIData('subscriptionID'))) ->needTriggers(true) ->executeOne(); if (!$subscription) { @@ -179,7 +179,7 @@ $account = $subscription->getAccount(); $add_method_uri = urisprintf( - '/phortune/account/%d/card/new/?subscriptionID=%s', + '/account/%d/methods/new/?subscriptionID=%s', $account->getID(), $subscription->getID()); $add_method_uri = $this->getApplicationURI($add_method_uri); diff --git a/src/applications/phortune/controller/charge/PhortuneChargeListController.php b/src/applications/phortune/controller/charge/PhortuneChargeListController.php deleted file mode 100644 --- a/src/applications/phortune/controller/charge/PhortuneChargeListController.php +++ /dev/null @@ -1,74 +0,0 @@ -getViewer(); - $querykey = $request->getURIData('queryKey'); - $account_id = $request->getURIData('accountID'); - - $engine = new PhortuneChargeSearchEngine(); - - if ($account_id) { - $account = id(new PhortuneAccountQuery()) - ->setViewer($viewer) - ->withIDs(array($account_id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$account) { - return new Aphront404Response(); - } - $this->account = $account; - $engine->setAccount($account); - } else { - return new Aphront404Response(); - } - - $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($querykey) - ->setSearchEngine($engine) - ->setNavigation($this->buildSideNavView()); - - return $this->delegateToController($controller); - } - - public function buildSideNavView() { - $viewer = $this->getViewer(); - - $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - - id(new PhortuneChargeSearchEngine()) - ->setViewer($viewer) - ->addNavigationItems($nav->getMenu()); - - $nav->selectFilter(null); - - return $nav; - } - - protected function buildApplicationCrumbs() { - $crumbs = parent::buildApplicationCrumbs(); - - $account = $this->account; - if ($account) { - $id = $account->getID(); - $crumbs->addTextCrumb( - $account->getName(), - $this->getApplicationURI("{$id}/")); - $crumbs->addTextCrumb( - pht('Charges'), - $this->getApplicationURI("{$id}/charge/")); - } - - return $crumbs; - } - -} diff --git a/src/applications/phortune/query/PhortuneCartSearchEngine.php b/src/applications/phortune/query/PhortuneCartSearchEngine.php --- a/src/applications/phortune/query/PhortuneCartSearchEngine.php +++ b/src/applications/phortune/query/PhortuneCartSearchEngine.php @@ -62,26 +62,8 @@ $merchant = $this->getMerchant(); $account = $this->getAccount(); if ($merchant) { - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $merchant, - PhabricatorPolicyCapability::CAN_EDIT); - if (!$can_edit) { - throw new Exception( - pht('You can not query orders for a merchant you do not control.')); - } $query->withMerchantPHIDs(array($merchant->getPHID())); } else if ($account) { - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $account, - PhabricatorPolicyCapability::CAN_EDIT); - if (!$can_edit) { - throw new Exception( - pht( - 'You can not query orders for an account you are not '. - 'a member of.')); - } $query->withAccountPHIDs(array($account->getPHID())); } else { $accounts = id(new PhortuneAccountQuery()) @@ -125,7 +107,7 @@ if ($merchant) { return '/phortune/merchant/orders/'.$merchant->getID().'/'.$path; } else if ($account) { - return '/phortune/'.$account->getID().'/order/'.$path; + return $account->getOrderListURI($path); } else { return '/phortune/order/'.$path; } diff --git a/src/applications/phortune/query/PhortuneChargeSearchEngine.php b/src/applications/phortune/query/PhortuneChargeSearchEngine.php --- a/src/applications/phortune/query/PhortuneChargeSearchEngine.php +++ b/src/applications/phortune/query/PhortuneChargeSearchEngine.php @@ -40,16 +40,6 @@ $account = $this->getAccount(); if ($account) { - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $account, - PhabricatorPolicyCapability::CAN_EDIT); - if (!$can_edit) { - throw new Exception( - pht( - 'You can not query charges for an account you are not '. - 'a member of.')); - } $query->withAccountPHIDs(array($account->getPHID())); } else { $accounts = id(new PhortuneAccountQuery()) diff --git a/src/applications/phortune/storage/PhortuneAccount.php b/src/applications/phortune/storage/PhortuneAccount.php --- a/src/applications/phortune/storage/PhortuneAccount.php +++ b/src/applications/phortune/storage/PhortuneAccount.php @@ -102,7 +102,9 @@ } public function getURI() { - return '/phortune/'.$this->getID().'/'; + return urisprintf( + '/phortune/account/%d/', + $this->getID()); } public function getDetailsURI() { @@ -111,6 +113,25 @@ $this->getID()); } + public function getOrdersURI() { + return urisprintf( + '/phortune/account/%d/orders/', + $this->getID()); + } + + public function getOrderListURI($path = '') { + return urisprintf( + '/phortune/account/%d/orders/list/%s', + $this->getID(), + $path); + } + + public function getSubscriptionsURI() { + return urisprintf( + '/phortune/account/%d/subscriptions/', + $this->getID()); + } + public function getEmailAddressesURI() { return urisprintf( '/phortune/account/%d/addresses/', @@ -123,6 +144,19 @@ $this->getID()); } + public function getChargesURI() { + return urisprintf( + '/phortune/account/%d/charges/', + $this->getID()); + } + + public function getChargeListURI($path = '') { + return urisprintf( + '/phortune/account/%d/charges/list/%s', + $this->getID(), + $path); + } + public function attachMerchantPHIDs(array $merchant_phids) { $this->merchantPHIDs = $merchant_phids; return $this; diff --git a/src/applications/phortune/storage/PhortuneCart.php b/src/applications/phortune/storage/PhortuneCart.php --- a/src/applications/phortune/storage/PhortuneCart.php +++ b/src/applications/phortune/storage/PhortuneCart.php @@ -3,7 +3,8 @@ final class PhortuneCart extends PhortuneDAO implements PhabricatorApplicationTransactionInterface, - PhabricatorPolicyInterface { + PhabricatorPolicyInterface, + PhabricatorExtendedPolicyInterface { const STATUS_BUILDING = 'cart:building'; const STATUS_READY = 'cart:ready'; @@ -652,26 +653,15 @@ } public function getPolicy($capability) { - // NOTE: Both view and edit use the account's edit policy. We punch a hole - // through this for merchants, below. - return $this - ->getAccount() - ->getPolicy(PhabricatorPolicyCapability::CAN_EDIT); + return PhabricatorPolicies::getMostOpenPolicy(); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { - if ($this->getAccount()->hasAutomaticCapability($capability, $viewer)) { - return true; - } - - // If the viewer controls the merchant this order was placed with, they - // can view the order. - if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { - $can_admin = PhabricatorPolicyFilter::hasCapability( - $viewer, - $this->getMerchant(), - PhabricatorPolicyCapability::CAN_EDIT); - if ($can_admin) { + if ($capability === PhabricatorPolicyCapability::CAN_VIEW) { + $any_edit = PhortuneMerchantQuery::canViewersEditMerchants( + array($viewer->getPHID()), + array($this->getMerchantPHID())); + if ($any_edit) { return true; } } @@ -679,10 +669,20 @@ return false; } - public function describeAutomaticCapability($capability) { + +/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ + + + public function getExtendedPolicy($capability, PhabricatorUser $viewer) { + if ($this->hasAutomaticCapability($capability, $viewer)) { + return array(); + } + return array( - pht('Orders inherit the policies of the associated account.'), - pht('The merchant you placed an order with can review and manage it.'), + array( + $this->getAccount(), + PhabricatorPolicyCapability::CAN_EDIT, + ), ); } diff --git a/src/applications/phortune/storage/PhortuneCharge.php b/src/applications/phortune/storage/PhortuneCharge.php --- a/src/applications/phortune/storage/PhortuneCharge.php +++ b/src/applications/phortune/storage/PhortuneCharge.php @@ -7,7 +7,9 @@ * charge followed by a successful charge. */ final class PhortuneCharge extends PhortuneDAO - implements PhabricatorPolicyInterface { + implements + PhabricatorPolicyInterface, + PhabricatorExtendedPolicyInterface { const STATUS_CHARGING = 'charge:charging'; const STATUS_CHARGED = 'charge:charged'; @@ -162,19 +164,42 @@ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { - return $this->getAccount()->getPolicy($capability); + return PhabricatorPolicies::getMostOpenPolicy(); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { - return $this->getAccount()->hasAutomaticCapability($capability, $viewer); + if ($capability === PhabricatorPolicyCapability::CAN_VIEW) { + $any_edit = PhortuneMerchantQuery::canViewersEditMerchants( + array($viewer->getPHID()), + array($this->getMerchantPHID())); + if ($any_edit) { + return true; + } + } + + return false; } - public function describeAutomaticCapability($capability) { - return pht('Charges inherit the policies of the associated account.'); + +/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ + + + public function getExtendedPolicy($capability, PhabricatorUser $viewer) { + if ($this->hasAutomaticCapability($capability, $viewer)) { + return array(); + } + + return array( + array( + $this->getAccount(), + PhabricatorPolicyCapability::CAN_EDIT, + ), + ); } } diff --git a/src/applications/phortune/storage/PhortuneSubscription.php b/src/applications/phortune/storage/PhortuneSubscription.php --- a/src/applications/phortune/storage/PhortuneSubscription.php +++ b/src/applications/phortune/storage/PhortuneSubscription.php @@ -189,10 +189,10 @@ } public function getURI() { - $account_id = $this->getAccount()->getID(); - $id = $this->getID(); - - return "/phortune/{$account_id}/subscription/view/{$id}/"; + return urisprintf( + '/phortune/account/%d/subscriptions/%d/', + $this->getAccount()->getID(), + $this->getID()); } public function getEditURI() {