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

Update Phortune payment account interfaces to handle merchant vs customer views

Summary: Depends on D20716. Ref T13366. This implements the new policy behavior cleanly in all top-level Phortune payment account interfaces.

Test Plan: As a merchant with an account relationship (not an account member) and an account member, browsed all account interfaces and attempted to perform edits. As a merchant, saw a reduced-strength view.

Maniphest Tasks: T13366

Differential Revision: https://secure.phabricator.com/D20717
This commit is contained in:
epriestley 2019-08-16 09:23:59 -07:00
parent a3213ab20b
commit 0cc7e8eeb8
19 changed files with 277 additions and 149 deletions

View file

@ -5222,7 +5222,6 @@ phutil_register_library_map(array(
'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php', 'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php',
'PhortuneAccountBillingAddressTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingAddressTransaction.php', 'PhortuneAccountBillingAddressTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingAddressTransaction.php',
'PhortuneAccountBillingNameTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingNameTransaction.php', 'PhortuneAccountBillingNameTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingNameTransaction.php',
'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php',
'PhortuneAccountChargesController' => 'applications/phortune/controller/account/PhortuneAccountChargesController.php', 'PhortuneAccountChargesController' => 'applications/phortune/controller/account/PhortuneAccountChargesController.php',
'PhortuneAccountController' => 'applications/phortune/controller/account/PhortuneAccountController.php', 'PhortuneAccountController' => 'applications/phortune/controller/account/PhortuneAccountController.php',
'PhortuneAccountDetailsController' => 'applications/phortune/controller/account/PhortuneAccountDetailsController.php', 'PhortuneAccountDetailsController' => 'applications/phortune/controller/account/PhortuneAccountDetailsController.php',
@ -5277,6 +5276,7 @@ phutil_register_library_map(array(
'PhortuneCartUpdateController' => 'applications/phortune/controller/cart/PhortuneCartUpdateController.php', 'PhortuneCartUpdateController' => 'applications/phortune/controller/cart/PhortuneCartUpdateController.php',
'PhortuneCartViewController' => 'applications/phortune/controller/cart/PhortuneCartViewController.php', 'PhortuneCartViewController' => 'applications/phortune/controller/cart/PhortuneCartViewController.php',
'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php', 'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php',
'PhortuneChargeListController' => 'applications/phortune/controller/charge/PhortuneChargeListController.php',
'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php', 'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php',
'PhortuneChargeQuery' => 'applications/phortune/query/PhortuneChargeQuery.php', 'PhortuneChargeQuery' => 'applications/phortune/query/PhortuneChargeQuery.php',
'PhortuneChargeSearchEngine' => 'applications/phortune/query/PhortuneChargeSearchEngine.php', 'PhortuneChargeSearchEngine' => 'applications/phortune/query/PhortuneChargeSearchEngine.php',
@ -11769,10 +11769,9 @@ phutil_register_library_map(array(
'PhabricatorApplicationTransactionInterface', 'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface', 'PhabricatorPolicyInterface',
), ),
'PhortuneAccountAddManagerController' => 'PhortuneController', 'PhortuneAccountAddManagerController' => 'PhortuneAccountController',
'PhortuneAccountBillingAddressTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountBillingAddressTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountBillingNameTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountBillingNameTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountChargeListController' => 'PhortuneController',
'PhortuneAccountChargesController' => 'PhortuneAccountProfileController', 'PhortuneAccountChargesController' => 'PhortuneAccountProfileController',
'PhortuneAccountController' => 'PhortuneController', 'PhortuneAccountController' => 'PhortuneController',
'PhortuneAccountDetailsController' => 'PhortuneAccountProfileController', 'PhortuneAccountDetailsController' => 'PhortuneAccountProfileController',
@ -11839,6 +11838,7 @@ phutil_register_library_map(array(
'PhortuneDAO', 'PhortuneDAO',
'PhabricatorPolicyInterface', 'PhabricatorPolicyInterface',
), ),
'PhortuneChargeListController' => 'PhortuneController',
'PhortuneChargePHIDType' => 'PhabricatorPHIDType', 'PhortuneChargePHIDType' => 'PhabricatorPHIDType',
'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine',

View file

@ -39,8 +39,6 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
'card/' => array( 'card/' => array(
'new/' => 'PhortunePaymentMethodCreateController', 'new/' => 'PhortunePaymentMethodCreateController',
), ),
'order/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneCartListController',
'subscription/' => array( 'subscription/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' '(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneSubscriptionListController', => 'PhortuneSubscriptionListController',
@ -51,8 +49,10 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
'order/(?P<subscriptionID>\d+)/' 'order/(?P<subscriptionID>\d+)/'
=> 'PhortuneCartListController', => 'PhortuneCartListController',
), ),
'order/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneCartListController',
'charge/(?:query/(?P<queryKey>[^/]+)/)?' 'charge/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneAccountChargeListController', => 'PhortuneChargeListController',
), ),
'card/(?P<id>\d+)/' => array( 'card/(?P<id>\d+)/' => array(
'edit/' => 'PhortunePaymentMethodEditController', 'edit/' => 'PhortunePaymentMethodEditController',
@ -82,16 +82,12 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
), ),
'addresses/' => array( 'addresses/' => array(
'' => 'PhortuneAccountEmailAddressesController', '' => 'PhortuneAccountEmailAddressesController',
$this->getEditRoutePattern('edit/')
=> 'PhortuneAccountEmailEditController',
),
),
),
'address/' => array(
'(?P<id>\d+)/' => 'PhortuneAccountEmailViewController', '(?P<id>\d+)/' => 'PhortuneAccountEmailViewController',
$this->getEditRoutePattern('edit/') $this->getEditRoutePattern('edit/')
=> 'PhortuneAccountEmailEditController', => 'PhortuneAccountEmailEditController',
), ),
),
),
'product/' => array( 'product/' => array(
'' => 'PhortuneProductListController', '' => 'PhortuneProductListController',
'view/(?P<id>\d+)/' => 'PhortuneProductViewController', 'view/(?P<id>\d+)/' => 'PhortuneProductViewController',

View file

@ -1,24 +1,18 @@
<?php <?php
final class PhortuneAccountAddManagerController extends PhortuneController { final class PhortuneAccountAddManagerController
extends PhortuneAccountController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$viewer = $request->getViewer(); return true;
$id = $request->getURIData('accountID');
$account = id(new PhortuneAccountQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$account) {
return new Aphront404Response();
} }
protected function handleAccountRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$account = $this->getAccount();
$id = $account->getID();
$v_managers = array(); $v_managers = array();
$e_managers = null; $e_managers = null;
$account_uri = $this->getApplicationURI("/account/{$id}/managers/"); $account_uri = $this->getApplicationURI("/account/{$id}/managers/");
@ -53,12 +47,24 @@ final class PhortuneAccountAddManagerController extends PhortuneController {
} }
} }
$account_phid = $account->getPHID();
$handles = $viewer->loadHandles(array($account_phid));
$handle = $handles[$account_phid];
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($viewer) ->setViewer($viewer)
->appendInstructions(
pht(
'Choose one or more users to add as account managers. Managers '.
'have full control of the account.'))
->appendControl(
id(new AphrontFormStaticControl())
->setLabel(pht('Payment Account'))
->setValue($handle->renderLink()))
->appendControl( ->appendControl(
id(new AphrontFormTokenizerControl()) id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorPeopleDatasource()) ->setDatasource(new PhabricatorPeopleDatasource())
->setLabel(pht('Managers')) ->setLabel(pht('Add Managers'))
->setName('managerPHIDs') ->setName('managerPHIDs')
->setValue($v_managers) ->setValue($v_managers)
->setError($e_managers)); ->setError($e_managers));
@ -69,7 +75,6 @@ final class PhortuneAccountAddManagerController extends PhortuneController {
->setWidth(AphrontDialogView::WIDTH_FORM) ->setWidth(AphrontDialogView::WIDTH_FORM)
->addCancelButton($account_uri) ->addCancelButton($account_uri)
->addSubmitButton(pht('Add Managers')); ->addSubmitButton(pht('Add Managers'));
} }
} }

View file

@ -3,25 +3,27 @@
final class PhortuneAccountChargesController final class PhortuneAccountChargesController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return false;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs()
$crumbs->addTextCrumb(pht('Order History')); ->addTextCrumb(pht('Order History'))
->setBorder(true);
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$charge_history = $this->buildChargeHistorySection($account); $charge_history = $this->buildChargeHistorySection($account);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter( ->setFooter(
array( array(
$authority,
$charge_history, $charge_history,
)); ));

View file

@ -4,14 +4,34 @@ abstract class PhortuneAccountController
extends PhortuneController { extends PhortuneController {
private $account; private $account;
private $merchants;
protected function getAccount() { final public function handleRequest(AphrontRequest $request) {
return $this->account; if ($this->shouldRequireAccountEditCapability()) {
$response = $this->loadAccountForEdit();
} else {
$response = $this->loadAccountForView();
} }
protected function setAccount(PhortuneAccount $account) { if ($response) {
$this->account = $account; return $response;
return $this; }
return $this->handleAccountRequest($request);
}
abstract protected function shouldRequireAccountEditCapability();
abstract protected function handleAccountRequest(AphrontRequest $request);
final protected function getAccount() {
if ($this->account === null) {
throw new Exception(
pht(
'Unable to "getAccount()" before loading or setting account '.
'context.'));
}
return $this->account;
} }
protected function buildApplicationCrumbs() { protected function buildApplicationCrumbs() {
@ -25,44 +45,112 @@ abstract class PhortuneAccountController
return $crumbs; return $crumbs;
} }
protected function loadAccount() { private function loadAccountForEdit() {
// TODO: Currently, you must be able to edit an account to view the detail return $this->loadAccountWithCapabilities(
// page, because the account must be broadly visible so merchants can array(
// process orders but merchants should not be able to see all the details PhabricatorPolicyCapability::CAN_VIEW,
// of an account. Ideally the profile pages should be visible to merchants, PhabricatorPolicyCapability::CAN_EDIT,
// too, just with less information. ));
return $this->loadAccountForEdit();
} }
protected function loadAccountForEdit() { private function loadAccountForView() {
return $this->loadAccountWithCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
));
}
private function loadAccountWithCapabilities(array $capabilities) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$request = $this->getRequest(); $request = $this->getRequest();
$account_id = $request->getURIData('accountID'); $account_id = $request->getURIData('accountID');
if (!$account_id) { if (!$account_id) {
$account_id = $request->getURIData('id'); throw new Exception(
} pht(
'Controller ("%s") extends controller "%s", but is reachable '.
if (!$account_id) { 'with no "accountID" in URI.',
return new Aphront404Response(); get_class($this),
__CLASS__));
} }
$account = id(new PhortuneAccountQuery()) $account = id(new PhortuneAccountQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($account_id)) ->withIDs(array($account_id))
->requireCapabilities( ->requireCapabilities($capabilities)
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne(); ->executeOne();
if (!$account) { if (!$account) {
return new Aphront404Response(); return new Aphront404Response();
} }
$this->account = $account; $this->setAccount($account);
return null; return null;
} }
private function setAccount(PhortuneAccount $account) {
$this->account = $account;
$viewer = $this->getViewer();
if (!$account->isUserAccountMember($viewer)) {
$merchant_phids = $account->getMerchantPHIDs();
$merchants = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->withPHIDs($merchant_phids)
->withMemberPHIDs(array($viewer->getPHID()))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$this->merchants = $merchants;
} else {
$this->merchants = array();
}
return $this;
}
final protected function getMerchants() {
if ($this->merchants === null) {
throw new Exception(
pht(
'Unable to "getMerchants()" before loading or setting account '.
'context.'));
}
return $this->merchants;
}
final protected function newAccountAuthorityView() {
$viewer = $this->getViewer();
$merchants = $this->getMerchants();
if (!$merchants) {
return null;
}
$merchant_phids = mpull($merchants, 'getPHID');
$merchant_handles = $viewer->loadHandles($merchant_phids);
$merchant_handles = iterator_to_array($merchant_handles);
$merchant_list = mpull($merchant_handles, 'renderLink');
$merchant_list = phutil_implode_html(', ', $merchant_list);
$merchant_message = pht(
'You can view this account because you control %d merchant(s) it '.
'has a relationship with: %s.',
phutil_count($merchants),
$merchant_list);
return id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setErrors(
array(
$merchant_message,
));
}
} }

View file

@ -3,12 +3,11 @@
final class PhortuneAccountDetailsController final class PhortuneAccountDetailsController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return true;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
@ -26,6 +25,7 @@ final class PhortuneAccountDetailsController
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$details = $this->newDetailsView($account); $details = $this->newDetailsView($account);
$curtain = $this->buildCurtainView($account); $curtain = $this->buildCurtainView($account);
@ -41,6 +41,7 @@ final class PhortuneAccountDetailsController
->setCurtain($curtain) ->setCurtain($curtain)
->setMainColumn( ->setMainColumn(
array( array(
$authority,
$details, $details,
$timeline, $timeline,
)); ));

View file

@ -3,25 +3,27 @@
final class PhortuneAccountEmailAddressesController final class PhortuneAccountEmailAddressesController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return true;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs()
$crumbs->addTextCrumb(pht('Email Addresses')); ->addTextCrumb(pht('Email Addresses'))
->setBorder(true);
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$addresses = $this->buildAddressesSection($account); $addresses = $this->buildAddressesSection($account);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter( ->setFooter(
array( array(
$authority,
$addresses, $addresses,
)); ));

View file

@ -3,23 +3,17 @@
final class PhortuneAccountEmailEditController final class PhortuneAccountEmailEditController
extends PhortuneAccountController { extends PhortuneAccountController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
return true;
}
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount();
$engine = id(new PhortuneAccountEmailEditEngine()) $engine = id(new PhortuneAccountEmailEditEngine())
->setController($this); ->setController($this);
if (!$request->getURIData('id')) { if (!$request->getURIData('id')) {
if (!$request->getURIData('accountID')) {
return new Aphront404Response();
}
$response = $this->loadAccount();
if ($response) {
return $response;
}
$account = $this->getAccount();
$engine->setAccount($account); $engine->setAccount($account);
} }

View file

@ -3,20 +3,23 @@
final class PhortuneAccountEmailViewController final class PhortuneAccountEmailViewController
extends PhortuneAccountController { extends PhortuneAccountController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
return true;
}
protected function handleAccountRequest(AphrontRequest $request) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$account = $this->getAccount();
$address = id(new PhortuneAccountEmailQuery()) $address = id(new PhortuneAccountEmailQuery())
->setViewer($viewer) ->setViewer($viewer)
->withAccountPHIDs(array($account->getPHID()))
->withIDs(array($request->getURIData('id'))) ->withIDs(array($request->getURIData('id')))
->executeOne(); ->executeOne();
if (!$address) { if (!$address) {
return new Aphront404Response(); return new Aphront404Response();
} }
$account = $address->getAccount();
$this->setAccount($account);
$crumbs = $this->buildApplicationCrumbs() $crumbs = $this->buildApplicationCrumbs()
->addTextCrumb(pht('Email Addresses'), $account->getEmailAddressesURI()) ->addTextCrumb(pht('Email Addresses'), $account->getEmailAddressesURI())
->addTextCrumb($address->getObjectName()) ->addTextCrumb($address->getObjectName())
@ -61,7 +64,8 @@ final class PhortuneAccountEmailViewController
$edit_uri = $this->getApplicationURI( $edit_uri = $this->getApplicationURI(
urisprintf( urisprintf(
'address/edit/%d/', 'account/%d/addresses/edit/%d/',
$account->getID(),
$address->getID())); $address->getID()));
$curtain = $this->newCurtainView($account); $curtain = $this->newCurtainView($account);

View file

@ -3,24 +3,27 @@
final class PhortuneAccountManagersController final class PhortuneAccountManagersController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return false;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs()
$crumbs->addTextCrumb(pht('Managers')); ->addTextCrumb(pht('Managers'))
->setBorder(true);
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$members = $this->buildMembersSection($account); $members = $this->buildMembersSection($account);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter(array( ->setFooter(
array(
$authority,
$members, $members,
)); ));

View file

@ -3,25 +3,28 @@
final class PhortuneAccountOrdersController final class PhortuneAccountOrdersController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return false;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs()
$crumbs->addTextCrumb(pht('Order History')); ->addTextCrumb(pht('Order History'))
->setBorder(true);
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$order_history = $this->newRecentOrdersView($account, 100); $order_history = $this->newRecentOrdersView($account, 100);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter( ->setFooter(
array( array(
$authority,
$order_history, $order_history,
)); ));

View file

@ -3,12 +3,11 @@
final class PhortuneAccountOverviewController final class PhortuneAccountOverviewController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return false;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
@ -26,6 +25,7 @@ final class PhortuneAccountOverviewController
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$status = $this->buildStatusView($account, $invoices); $status = $this->buildStatusView($account, $invoices);
$invoices = $this->buildInvoicesSection($account, $invoices); $invoices = $this->buildInvoicesSection($account, $invoices);
$purchase_history = $this->newRecentOrdersView($account, 10); $purchase_history = $this->newRecentOrdersView($account, 10);
@ -34,6 +34,7 @@ final class PhortuneAccountOverviewController
->setHeader($header) ->setHeader($header)
->setFooter( ->setFooter(
array( array(
$authority,
$status, $status,
$invoices, $invoices,
$purchase_history, $purchase_history,

View file

@ -3,18 +3,19 @@
final class PhortuneAccountPaymentMethodsController final class PhortuneAccountPaymentMethodsController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return false;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs()
$crumbs->addTextCrumb(pht('Payment Methods')); ->addTextCrumb(pht('Payment Methods'))
->setBorder(true);
$authority = $this->newAccountAuthorityView();
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$methods = $this->buildPaymentMethodsSection($account); $methods = $this->buildPaymentMethodsSection($account);
@ -22,6 +23,7 @@ final class PhortuneAccountPaymentMethodsController
->setHeader($header) ->setHeader($header)
->setFooter( ->setFooter(
array( array(
$authority,
$methods, $methods,
)); ));

View file

@ -17,13 +17,16 @@ abstract class PhortuneAccountProfileController
->setHeader($title) ->setHeader($title)
->setHeaderIcon('fa-user-circle'); ->setHeaderIcon('fa-user-circle');
return $header; if ($this->getMerchants()) {
$customer_tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE)
->setName(pht('Customer Account'))
->setColor('indigo')
->setIcon('fa-credit-card');
$header->addTag($customer_tag);
} }
protected function buildApplicationCrumbs() { return $header;
$crumbs = parent::buildApplicationCrumbs();
$crumbs->setBorder(true);
return $crumbs;
} }
protected function buildSideNavView($filter = null) { protected function buildSideNavView($filter = null) {
@ -31,6 +34,8 @@ abstract class PhortuneAccountProfileController
$account = $this->getAccount(); $account = $this->getAccount();
$id = $account->getID(); $id = $account->getID();
$can_edit = !$this->getMerchants();
$nav = id(new AphrontSideNavFilterView()) $nav = id(new AphrontSideNavFilterView())
->setBaseURI(new PhutilURI($this->getApplicationURI())); ->setBaseURI(new PhutilURI($this->getApplicationURI()));
@ -42,11 +47,12 @@ abstract class PhortuneAccountProfileController
$this->getApplicationURI("/{$id}/"), $this->getApplicationURI("/{$id}/"),
'fa-user-circle'); 'fa-user-circle');
$nav->addFilter( $nav->newLink('details')
'details', ->setName(pht('Account Details'))
pht('Account Details'), ->setHref($this->getApplicationURI("/account/{$id}/details/"))
$this->getApplicationURI("/account/{$id}/details/"), ->setIcon('fa-address-card-o')
'fa-address-card-o'); ->setWorkflow(!$can_edit)
->setDisabled(!$can_edit);
$nav->addLabel(pht('Payments')); $nav->addLabel(pht('Payments'));
@ -82,11 +88,12 @@ abstract class PhortuneAccountProfileController
$this->getApplicationURI("/account/{$id}/managers/"), $this->getApplicationURI("/account/{$id}/managers/"),
'fa-group'); 'fa-group');
$nav->addFilter( $nav->newLink('addresses')
'addresses', ->setname(pht('Email Addresses'))
pht('Email Addresses'), ->setHref($this->getApplicationURI("/account/{$id}/addresses/"))
$this->getApplicationURI("/account/{$id}/addresses/"), ->setIcon('fa-envelope-o')
'fa-envelope-o'); ->setWorkflow(!$can_edit)
->setDisabled(!$can_edit);
$nav->selectFilter($filter); $nav->selectFilter($filter);

View file

@ -3,24 +3,28 @@
final class PhortuneAccountSubscriptionController final class PhortuneAccountSubscriptionController
extends PhortuneAccountProfileController { extends PhortuneAccountProfileController {
public function handleRequest(AphrontRequest $request) { protected function shouldRequireAccountEditCapability() {
$response = $this->loadAccount(); return false;
if ($response) {
return $response;
} }
protected function handleAccountRequest(AphrontRequest $request) {
$account = $this->getAccount(); $account = $this->getAccount();
$title = $account->getName(); $title = $account->getName();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs()
$crumbs->addTextCrumb(pht('Subscriptions')); ->addTextCrumb(pht('Subscriptions'))
->setBorder(true);
$header = $this->buildHeaderView(); $header = $this->buildHeaderView();
$authority = $this->newAccountAuthorityView();
$subscriptions = $this->buildSubscriptionsSection($account); $subscriptions = $this->buildSubscriptionsSection($account);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter(array( ->setFooter(
array(
$authority,
$subscriptions, $subscriptions,
)); ));

View file

@ -1,6 +1,6 @@
<?php <?php
final class PhortuneAccountChargeListController final class PhortuneChargeListController
extends PhortuneController { extends PhortuneController {
private $account; private $account;

View file

@ -138,6 +138,17 @@ final class PhortuneAccount extends PhortuneDAO
return $this; return $this;
} }
public function isUserAccountMember(PhabricatorUser $user) {
$user_phid = $user->getPHID();
if (!$user_phid) {
return null;
}
$member_map = array_fuse($this->getMemberPHIDs());
return isset($member_map[$user_phid]);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */ /* -( PhabricatorApplicationTransactionInterface )------------------------- */
@ -174,8 +185,7 @@ final class PhortuneAccount extends PhortuneDAO
} }
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
$members = array_fuse($this->getMemberPHIDs()); if ($this->isUserAccountMember($viewer)) {
if (isset($members[$viewer->getPHID()])) {
return true; return true;
} }

View file

@ -73,7 +73,8 @@ final class PhortuneAccountEmail
public function getURI() { public function getURI() {
return urisprintf( return urisprintf(
'/phortune/address/%d/', '/phortune/account/%d/addresses/%d/',
$this->getAccount()->getID(),
$this->getID()); $this->getID());
} }

View file

@ -111,6 +111,11 @@ final class AphrontSideNavFilterView extends AphrontView {
$key, $name, $uri, PHUIListItemView::TYPE_BUTTON); $key, $name, $uri, PHUIListItemView::TYPE_BUTTON);
} }
public function newLink($key) {
$this->addFilter($key, '');
return $this->getMenuView()->getItem($key);
}
private function addThing($key, $name, $uri, $type, $icon = null) { private function addThing($key, $name, $uri, $type, $icon = null) {
$item = id(new PHUIListItemView()) $item = id(new PHUIListItemView())
->setName($name) ->setName($name)