1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 14:00:56 +01:00

Update Charge and Cart policies in Phortune, and make URIs more consistent

Summary:
Ref T13366. Depends on D20721. Continue applying UI and policy updates to the last two Phortune objects.

Charges aren't mutable and Carts are already transactional, so this is less involved than prior changes.

Test Plan: Viewed various charge/order interfaces as merchants and account members.

Maniphest Tasks: T13366

Differential Revision: https://secure.phabricator.com/D20732
This commit is contained in:
epriestley 2019-08-22 14:23:23 -07:00
parent a542024b63
commit c93ac91dc6
16 changed files with 218 additions and 172 deletions

View file

@ -5222,6 +5222,7 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'PhortuneAccountAddManagerController' => 'PhortuneAccountController',
'PhortuneAccountBillingAddressTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountBillingNameTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountChargeListController' => 'PhortuneAccountProfileController',
'PhortuneAccountChargesController' => 'PhortuneAccountProfileController',
'PhortuneAccountController' => 'PhortuneController',
'PhortuneAccountDetailsController' => 'PhortuneAccountProfileController',
@ -11816,6 +11818,7 @@ phutil_register_library_map(array(
'PhortuneAccountListController' => 'PhortuneController',
'PhortuneAccountManagersController' => 'PhortuneAccountProfileController',
'PhortuneAccountNameTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountOrderListController' => 'PhortuneAccountProfileController',
'PhortuneAccountOrdersController' => 'PhortuneAccountProfileController',
'PhortuneAccountOverviewController' => 'PhortuneAccountProfileController',
'PhortuneAccountPHIDType' => 'PhabricatorPHIDType',
@ -11836,6 +11839,7 @@ phutil_register_library_map(array(
'PhortuneDAO',
'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface',
'PhabricatorExtendedPolicyInterface',
),
'PhortuneCartAcceptController' => 'PhortuneCartController',
'PhortuneCartCancelController' => 'PhortuneCartController',
@ -11855,8 +11859,8 @@ phutil_register_library_map(array(
'PhortuneCharge' => array(
'PhortuneDAO',
'PhabricatorPolicyInterface',
'PhabricatorExtendedPolicyInterface',
),
'PhortuneChargeListController' => 'PhortuneController',
'PhortuneChargePHIDType' => 'PhabricatorPHIDType',
'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine',

View file

@ -34,24 +34,6 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
return array(
'/phortune/' => array(
'' => 'PhortuneLandingController',
'(?P<accountID>\d+)/' => array(
'' => 'PhortuneAccountOverviewController',
'card/' => array(
'new/' => 'PhortunePaymentMethodCreateController',
),
'subscription/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneSubscriptionListController',
'view/(?P<id>\d+)/'
=> 'PhortuneAccountSubscriptionViewController',
'order/(?P<subscriptionID>\d+)/'
=> 'PhortuneCartListController',
),
'order/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneCartListController',
'charge/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhortuneChargeListController',
),
'card/(?P<id>\d+)/' => array(
'edit/' => 'PhortunePaymentMethodEditController',
'disable/' => 'PhortunePaymentMethodDisableController',
@ -65,22 +47,36 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
),
'account/' => array(
'' => 'PhortuneAccountListController',
$this->getEditRoutePattern('edit/')
=> 'PhortuneAccountEditController',
'(?P<accountID>\d+)/' => array(
'' => 'PhortuneAccountOverviewController',
'details/' => 'PhortuneAccountDetailsController',
'methods/' => array(
'' => 'PhortuneAccountPaymentMethodController',
'(?P<id>\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<subscriptionID>\d+)/' => array(
'' => 'PhortuneAccountSubscriptionViewController',
'autopay/(?P<methodID>\d+)/'
=> 'PhortuneAccountSubscriptionAutopayController',
$this->getQueryRoutePattern('orders/')
=> 'PhortuneAccountOrderListController',
),
),
'managers/' => array(

View file

@ -0,0 +1,35 @@
<?php
final class PhortuneAccountChargeListController
extends PhortuneAccountProfileController {
protected function shouldRequireAccountEditCapability() {
return false;
}
protected function handleAccountRequest(AphrontRequest $request) {
$viewer = $request->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;
}
}

View file

@ -56,7 +56,7 @@ final class PhortuneAccountChargesController
$handles = $this->loadViewerHandles($phids);
$charges_uri = $this->getApplicationURI($account->getID().'/charge/');
$charges_uri = $account->getChargeListURI();
$table = id(new PhortuneChargeTableView())
->setUser($viewer)

View file

@ -23,7 +23,7 @@ abstract class PhortuneAccountController
abstract protected function shouldRequireAccountEditCapability();
abstract protected function handleAccountRequest(AphrontRequest $request);
private function hasAccount() {
final protected function hasAccount() {
return (bool)$this->account;
}

View file

@ -0,0 +1,58 @@
<?php
final class PhortuneAccountOrderListController
extends PhortuneAccountProfileController {
private $subscription;
protected function shouldRequireAccountEditCapability() {
return false;
}
protected function handleAccountRequest(AphrontRequest $request) {
$viewer = $request->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;
}
}

View file

@ -50,7 +50,7 @@ final class PhortuneAccountPaymentMethodController
->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);

View file

@ -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 @@ abstract class PhortuneAccountProfileController
$nav->addFilter(
'overview',
pht('Overview'),
$this->getApplicationURI("/{$id}/"),
$account->getURI(),
'fa-user-circle');
$nav->newLink('details')
@ -59,25 +55,25 @@ abstract class PhortuneAccountProfileController
$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 @@ abstract class PhortuneAccountProfileController
$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 @@ abstract class PhortuneAccountProfileController
}
$handles = $this->loadViewerHandles($phids);
$orders_uri = $this->getApplicationURI($account->getID().'/order/');
$orders_uri = $account->getOrderListURI();
$table = id(new PhortuneOrderTableView())
->setUser($viewer)

View file

@ -12,7 +12,7 @@ final class PhortuneAccountSubscriptionViewController
$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 @@ final class PhortuneAccountSubscriptionViewController
$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);

View file

@ -1,74 +0,0 @@
<?php
final class PhortuneChargeListController
extends PhortuneController {
private $account;
public function handleRequest(AphrontRequest $request) {
$viewer = $request->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;
}
}

View file

@ -62,26 +62,8 @@ final class PhortuneCartSearchEngine
$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 @@ final class PhortuneCartSearchEngine
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;
}

View file

@ -40,16 +40,6 @@ final class PhortuneChargeSearchEngine
$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())

View file

@ -102,7 +102,9 @@ final class PhortuneAccount extends PhortuneDAO
}
public function getURI() {
return '/phortune/'.$this->getID().'/';
return urisprintf(
'/phortune/account/%d/',
$this->getID());
}
public function getDetailsURI() {
@ -111,6 +113,25 @@ final class PhortuneAccount extends PhortuneDAO
$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 @@ final class PhortuneAccount extends PhortuneDAO
$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;

View file

@ -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 @@ final class PhortuneCart extends PhortuneDAO
}
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 @@ final class PhortuneCart extends PhortuneDAO
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,
),
);
}

View file

@ -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 @@ final class PhortuneCharge extends PhortuneDAO
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,
),
);
}
}

View file

@ -189,10 +189,10 @@ final class PhortuneSubscription
}
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() {