mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Merge pull request #132 from sharetribe/transaction-pages-fix-links-with-wrong-role
Enforcing role on order & sale pages
This commit is contained in:
commit
9e18456d8a
6 changed files with 43 additions and 12 deletions
|
|
@ -46,7 +46,7 @@ export const fetchOrder = id =>
|
|||
dispatch(fetchOrderRequest());
|
||||
|
||||
return sdk.transactions
|
||||
.show({ id, include: ['provider', 'listing', 'booking'] }, { expand: true })
|
||||
.show({ id, include: ['customer', 'provider', 'listing', 'booking'] }, { expand: true })
|
||||
.then(response => {
|
||||
dispatch(addEntities(response));
|
||||
dispatch(fetchOrderSuccess(response));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { PropTypes } from 'react';
|
|||
import classNames from 'classnames';
|
||||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { OrderDetailsPanel, PageLayout } from '../../components';
|
||||
import { NamedRedirect, OrderDetailsPanel, PageLayout } from '../../components';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { ensureBooking, ensureListing, ensureTransaction, ensureUser } from '../../util/data';
|
||||
import { getEntities } from '../../ducks/sdk.duck';
|
||||
|
|
@ -13,11 +13,20 @@ import css from './OrderPage.css';
|
|||
// OrderPage handles data loading
|
||||
// It show loading data text or OrderDetailsPanel (and later also another panel for messages).
|
||||
export const OrderPageComponent = props => {
|
||||
const { intl, transaction } = props;
|
||||
const { currentUser, intl, transaction } = props;
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const title = currentListing.attributes.title;
|
||||
|
||||
// Redirect users with someone else's direct link to their own inbox/orders page.
|
||||
const isDataAvailable = currentUser && currentTransaction.id && currentTransaction.customer;
|
||||
const isOwnSale = isDataAvailable && currentUser.id.uuid === currentTransaction.customer.id.uuid;
|
||||
if (isDataAvailable && !isOwnSale) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Tried to access an order that was not owned by the current user');
|
||||
return <NamedRedirect name="InboxPage" params={{ tab: 'orders' }} />;
|
||||
}
|
||||
|
||||
const detailsProps = {
|
||||
totalPrice: currentTransaction.attributes.total,
|
||||
orderState: currentTransaction.attributes.state,
|
||||
|
|
@ -31,7 +40,7 @@ export const OrderPageComponent = props => {
|
|||
[css.tabContentVisible]: props.tab === 'details',
|
||||
});
|
||||
|
||||
const panel = currentTransaction.id
|
||||
const panel = isDataAvailable && currentTransaction.id
|
||||
? <OrderDetailsPanel className={detailsClassName} {...detailsProps} />
|
||||
: <h1 className={css.title}><FormattedMessage id="OrderPage.loadingData" /></h1>;
|
||||
|
||||
|
|
@ -42,11 +51,12 @@ export const OrderPageComponent = props => {
|
|||
);
|
||||
};
|
||||
|
||||
OrderPageComponent.defaultProps = { transaction: null };
|
||||
OrderPageComponent.defaultProps = { transaction: null, currentUser: null };
|
||||
|
||||
const { oneOf } = PropTypes;
|
||||
|
||||
OrderPageComponent.propTypes = {
|
||||
currentUser: propTypes.currentUser,
|
||||
intl: intlShape.isRequired,
|
||||
tab: oneOf(['details', 'discussion']).isRequired,
|
||||
transaction: propTypes.transaction,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
createBooking,
|
||||
createCurrentUser,
|
||||
createListing,
|
||||
createTransaction,
|
||||
createUser,
|
||||
|
|
@ -20,10 +21,12 @@ describe('OrderPage', () => {
|
|||
new Date(Date.UTC(2017, 5, 13))
|
||||
),
|
||||
listing: createListing('listing1'),
|
||||
customer: createUser('customer1'),
|
||||
provider: createUser('provider1'),
|
||||
});
|
||||
|
||||
const props = {
|
||||
currentUser: createCurrentUser('customer1'),
|
||||
transaction,
|
||||
tab: 'details',
|
||||
intl: fakeIntl,
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ export const fetchSale = id =>
|
|||
dispatch(fetchSaleRequest());
|
||||
|
||||
return sdk.transactions
|
||||
.show({ id, include: ['customer', 'listing', 'booking'] }, { expand: true })
|
||||
.show({ id, include: ['customer', 'provider', 'listing', 'booking'] }, { expand: true })
|
||||
.then(response => {
|
||||
dispatch(addEntities(response));
|
||||
dispatch(fetchSaleSuccess(response));
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { ensureBooking, ensureListing, ensureTransaction, ensureUser } from '../../util/data';
|
||||
import { Button, SaleDetailsPanel, PageLayout } from '../../components';
|
||||
import { Button, NamedRedirect, SaleDetailsPanel, PageLayout } from '../../components';
|
||||
import { getEntities } from '../../ducks/sdk.duck';
|
||||
import { acceptSale, rejectSale, loadData } from './SalePage.duck';
|
||||
|
||||
|
|
@ -13,11 +14,20 @@ import css from './SalePage.css';
|
|||
// SalePage handles data loading
|
||||
// It show loading data text or SaleDetailsPanel (and later also another panel for messages).
|
||||
export const SalePageComponent = props => {
|
||||
const { intl, onAcceptSale, onRejectSale, transaction } = props;
|
||||
const { currentUser, intl, onAcceptSale, onRejectSale, transaction } = props;
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const title = currentListing.attributes.title;
|
||||
|
||||
// Redirect users with someone else's direct link to their own inbox/sales page.
|
||||
const isDataAvailable = currentUser && currentTransaction.id && currentTransaction.provider;
|
||||
const isOwnSale = isDataAvailable && currentUser.id.uuid === currentTransaction.provider.id.uuid;
|
||||
if (isDataAvailable && !isOwnSale) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Tried to access a sale that was not owned by the current user');
|
||||
return <NamedRedirect name="InboxPage" params={{ tab: 'sales' }} />;
|
||||
}
|
||||
|
||||
const detailsProps = {
|
||||
subtotalPrice: currentTransaction.attributes.total,
|
||||
commission: currentTransaction.attributes.commission,
|
||||
|
|
@ -32,11 +42,13 @@ export const SalePageComponent = props => {
|
|||
[css.tabContentVisible]: props.tab === 'details',
|
||||
});
|
||||
|
||||
const panel = currentTransaction.id
|
||||
const panel = isDataAvailable && currentTransaction.id
|
||||
? <SaleDetailsPanel className={detailsClassName} {...detailsProps} />
|
||||
: <h1 className={css.title}><FormattedMessage id="SalePage.loadingData" /></h1>;
|
||||
|
||||
const actionButtons = currentTransaction.attributes.state === propTypes.TX_STATE_PREAUTHORIZED
|
||||
const isPreauthorizedState = currentTransaction.attributes.state ===
|
||||
propTypes.TX_STATE_PREAUTHORIZED;
|
||||
const actionButtons = isDataAvailable && isPreauthorizedState
|
||||
? <div className={css.actionButtons}>
|
||||
<Button className={css.rejectButton} onClick={() => onRejectSale(currentTransaction.id)}>
|
||||
<FormattedMessage id="SalePage.rejectButton" />
|
||||
|
|
@ -55,11 +67,12 @@ export const SalePageComponent = props => {
|
|||
);
|
||||
};
|
||||
|
||||
SalePageComponent.defaultProps = { transaction: null };
|
||||
SalePageComponent.defaultProps = { transaction: null, currentUser: null };
|
||||
|
||||
const { func, oneOf } = PropTypes;
|
||||
|
||||
SalePageComponent.propTypes = {
|
||||
currentUser: propTypes.currentUser,
|
||||
intl: intlShape.isRequired,
|
||||
onAcceptSale: func.isRequired,
|
||||
onRejectSale: func.isRequired,
|
||||
|
|
@ -85,7 +98,9 @@ const mapDispatchToProps = dispatch => {
|
|||
};
|
||||
};
|
||||
|
||||
const SalePage = connect(mapStateToProps, mapDispatchToProps)(injectIntl(SalePageComponent));
|
||||
const SalePage = compose(connect(mapStateToProps, mapDispatchToProps), injectIntl)(
|
||||
SalePageComponent
|
||||
);
|
||||
|
||||
SalePage.loadData = loadData;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
createBooking,
|
||||
createCurrentUser,
|
||||
createListing,
|
||||
createTransaction,
|
||||
createUser,
|
||||
|
|
@ -21,9 +22,11 @@ describe('SalePage', () => {
|
|||
),
|
||||
listing: createListing('listing1'),
|
||||
customer: createUser('customer1'),
|
||||
provider: createUser('provider1'),
|
||||
});
|
||||
|
||||
const props = {
|
||||
currentUser: createCurrentUser('provider1'),
|
||||
onAcceptSale: () => {},
|
||||
onRejectSale: () => {},
|
||||
transaction,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue