parent
2d4ff1dd82
commit
c76c9ca2c8
@ -0,0 +1,84 @@ |
|||||||
|
const ObservableStore = require('obs-store') |
||||||
|
|
||||||
|
/** |
||||||
|
* A controller that services user-approved requests for a full Ethereum provider API |
||||||
|
*/ |
||||||
|
class ProviderApprovalController { |
||||||
|
/** |
||||||
|
* Creates a ProviderApprovalController |
||||||
|
* |
||||||
|
* @param {Object} [config] - Options to configure controller |
||||||
|
*/ |
||||||
|
constructor ({ closePopup, openPopup, platform, publicConfigStore } = {}) { |
||||||
|
this.store = new ObservableStore() |
||||||
|
this.closePopup = closePopup |
||||||
|
this.openPopup = openPopup |
||||||
|
this.platform = platform |
||||||
|
this.publicConfigStore = publicConfigStore |
||||||
|
this.approvedOrigins = {} |
||||||
|
platform && platform.addMessageListener && platform.addMessageListener(({ action, origin }) => { |
||||||
|
action && action === 'init-provider-request' && this.handleProviderRequest(origin) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Called when a tab requests access to a full Ethereum provider API |
||||||
|
* |
||||||
|
* @param {string} origin - Origin of the window requesting full provider access |
||||||
|
*/ |
||||||
|
handleProviderRequest (origin) { |
||||||
|
this.store.updateState({ providerRequests: [{ origin }] }) |
||||||
|
if (this.approvedOrigins[origin]) { |
||||||
|
this.approveProviderRequest(origin) |
||||||
|
return |
||||||
|
} |
||||||
|
this.openPopup && this.openPopup() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Called when a user approves access to a full Ethereum provider API |
||||||
|
* |
||||||
|
* @param {string} origin - Origin of the target window to approve provider access |
||||||
|
*/ |
||||||
|
approveProviderRequest (origin) { |
||||||
|
this.closePopup && this.closePopup() |
||||||
|
const requests = this.store.getState().providerRequests || [] |
||||||
|
this.platform && this.platform.sendMessage({ action: 'approve-provider-request' }, { active: true }) |
||||||
|
this.publicConfigStore.emit('update', this.publicConfigStore.getState()) |
||||||
|
const providerRequests = requests.filter(request => request.origin !== origin) |
||||||
|
this.store.updateState({ providerRequests }) |
||||||
|
this.approvedOrigins[origin] = true |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Called when a tab rejects access to a full Ethereum provider API |
||||||
|
* |
||||||
|
* @param {string} origin - Origin of the target window to reject provider access |
||||||
|
*/ |
||||||
|
rejectProviderRequest (origin) { |
||||||
|
this.closePopup && this.closePopup() |
||||||
|
const requests = this.store.getState().providerRequests || [] |
||||||
|
this.platform && this.platform.sendMessage({ action: 'reject-provider-request' }, { active: true }) |
||||||
|
const providerRequests = requests.filter(request => request.origin !== origin) |
||||||
|
this.store.updateState({ providerRequests }) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Clears any cached approvals for user-approved origins |
||||||
|
*/ |
||||||
|
clearApprovedOrigins () { |
||||||
|
this.approvedOrigins = {} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determines if a given origin has been approved |
||||||
|
* |
||||||
|
* @param {string} origin - Domain origin to check for approval status |
||||||
|
* @returns {boolean} - True if the origin has been approved |
||||||
|
*/ |
||||||
|
isApproved (origin) { |
||||||
|
return this.approvedOrigins[origin] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = ProviderApprovalController |
@ -0,0 +1,64 @@ |
|||||||
|
import PropTypes from 'prop-types' |
||||||
|
import React, { Component } from 'react' |
||||||
|
import { approveProviderRequest, rejectProviderRequest } from '../../ui/app/actions' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
class ProviderApproval extends Component { |
||||||
|
render () { |
||||||
|
const { approveProviderRequest, origin, rejectProviderRequest } = this.props |
||||||
|
return ( |
||||||
|
<div className="flex-column flex-grow"> |
||||||
|
<style dangerouslySetInnerHTML={{__html: ` |
||||||
|
.provider_approval_actions { |
||||||
|
display: flex; |
||||||
|
justify-content: flex-end; |
||||||
|
margin: 14px 25px; |
||||||
|
} |
||||||
|
.provider_approval_actions button { |
||||||
|
margin-left: 10px; |
||||||
|
text-transform: uppercase; |
||||||
|
} |
||||||
|
.provider_approval_content { |
||||||
|
padding: 0 25px; |
||||||
|
} |
||||||
|
.provider_approval_origin { |
||||||
|
font-weight: bold; |
||||||
|
margin: 14px 0; |
||||||
|
} |
||||||
|
`}} />
|
||||||
|
<div className="section-title flex-row flex-center"> |
||||||
|
<i |
||||||
|
className="fa fa-arrow-left fa-lg cursor-pointer" |
||||||
|
onClick={() => { rejectProviderRequest(origin) }} /> |
||||||
|
<h2 className="page-subtitle">Web3 API Request</h2> |
||||||
|
</div> |
||||||
|
<div className="provider_approval_content"> |
||||||
|
{"The domain listed below is requesting access to the Ethereum blockchain and to view your current account. Always double check that you're on the correct site before approving access."} |
||||||
|
<div className="provider_approval_origin">{origin}</div> |
||||||
|
</div> |
||||||
|
<div className="provider_approval_actions"> |
||||||
|
<button |
||||||
|
className="btn-green" |
||||||
|
onClick={() => { approveProviderRequest(origin) }}>APPROVE</button> |
||||||
|
<button |
||||||
|
className="cancel btn-red" |
||||||
|
onClick={() => { rejectProviderRequest(origin) }}>REJECT</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ProviderApproval.propTypes = { |
||||||
|
approveProviderRequest: PropTypes.func, |
||||||
|
origin: PropTypes.string, |
||||||
|
rejectProviderRequest: PropTypes.func, |
||||||
|
} |
||||||
|
|
||||||
|
function mapDispatchToProps (dispatch) { |
||||||
|
return { |
||||||
|
approveProviderRequest: origin => dispatch(approveProviderRequest(origin)), |
||||||
|
rejectProviderRequest: origin => dispatch(rejectProviderRequest(origin)), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = connect(null, mapDispatchToProps)(ProviderApproval) |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,39 @@ |
|||||||
|
import React, { PureComponent } from 'react' |
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import Modal, { ModalContent } from '../../modal' |
||||||
|
|
||||||
|
export default class ClearApprovedOrigins extends PureComponent { |
||||||
|
static propTypes = { |
||||||
|
hideModal: PropTypes.func.isRequired, |
||||||
|
clearApprovedOrigins: PropTypes.func.isRequired, |
||||||
|
} |
||||||
|
|
||||||
|
static contextTypes = { |
||||||
|
t: PropTypes.func, |
||||||
|
} |
||||||
|
|
||||||
|
handleClear = () => { |
||||||
|
const { clearApprovedOrigins, hideModal } = this.props |
||||||
|
clearApprovedOrigins() |
||||||
|
hideModal() |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
const { t } = this.context |
||||||
|
|
||||||
|
return ( |
||||||
|
<Modal |
||||||
|
onSubmit={this.handleClear} |
||||||
|
onCancel={() => this.props.hideModal()} |
||||||
|
submitText={t('ok')} |
||||||
|
cancelText={t('nevermind')} |
||||||
|
submitType="secondary" |
||||||
|
> |
||||||
|
<ModalContent |
||||||
|
title={t('clearApprovalData')} |
||||||
|
description={t('confirmClear')} |
||||||
|
/> |
||||||
|
</Modal> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
import { connect } from 'react-redux' |
||||||
|
import { compose } from 'recompose' |
||||||
|
import withModalProps from '../../../higher-order-components/with-modal-props' |
||||||
|
import ClearApprovedOriginsComponent from './clear-approved-origins.component' |
||||||
|
import { clearApprovedOrigins } from '../../../actions' |
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => { |
||||||
|
return { |
||||||
|
clearApprovedOrigins: () => dispatch(clearApprovedOrigins()), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default compose( |
||||||
|
withModalProps, |
||||||
|
connect(null, mapDispatchToProps) |
||||||
|
)(ClearApprovedOriginsComponent) |
@ -0,0 +1 @@ |
|||||||
|
export { default } from './clear-approved-origins.container' |
@ -0,0 +1 @@ |
|||||||
|
export { default } from './provider-approval.container' |
@ -0,0 +1,35 @@ |
|||||||
|
import PageContainerContent from '../../page-container' |
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import React, { Component } from 'react' |
||||||
|
|
||||||
|
export default class ProviderApproval extends Component { |
||||||
|
static propTypes = { |
||||||
|
approveProviderRequest: PropTypes.func, |
||||||
|
origin: PropTypes.string, |
||||||
|
rejectProviderRequest: PropTypes.func, |
||||||
|
}; |
||||||
|
|
||||||
|
static contextTypes = { |
||||||
|
t: PropTypes.func, |
||||||
|
}; |
||||||
|
|
||||||
|
render () { |
||||||
|
const { approveProviderRequest, origin, rejectProviderRequest } = this.props |
||||||
|
return ( |
||||||
|
<PageContainerContent |
||||||
|
title={this.context.t('providerAPIRequest')} |
||||||
|
subtitle={this.context.t('reviewProviderRequest')} |
||||||
|
contentComponent={( |
||||||
|
<div className="provider_approval_content"> |
||||||
|
{this.context.t('providerRequestInfo')} |
||||||
|
<div className="provider_approval_origin">{origin}</div> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
submitText={this.context.t('approve')} |
||||||
|
cancelText={this.context.t('reject')} |
||||||
|
onSubmit={() => { approveProviderRequest(origin) }} |
||||||
|
onCancel={() => { rejectProviderRequest(origin) }} |
||||||
|
onClose={() => { rejectProviderRequest(origin) }} /> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
import { connect } from 'react-redux' |
||||||
|
import ProviderApproval from './provider-approval.component' |
||||||
|
import { approveProviderRequest, rejectProviderRequest } from '../../../actions' |
||||||
|
|
||||||
|
function mapDispatchToProps (dispatch) { |
||||||
|
return { |
||||||
|
approveProviderRequest: origin => dispatch(approveProviderRequest(origin)), |
||||||
|
rejectProviderRequest: origin => dispatch(rejectProviderRequest(origin)), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(ProviderApproval) |
@ -1 +1,3 @@ |
|||||||
@import './reveal-seed.scss'; |
@import './reveal-seed.scss'; |
||||||
|
|
||||||
|
@import './provider-approval.scss'; |
||||||
|
@ -0,0 +1,11 @@ |
|||||||
|
.provider_approval_content { |
||||||
|
height: auto; |
||||||
|
overflow: auto; |
||||||
|
padding: 16px; |
||||||
|
} |
||||||
|
|
||||||
|
.provider_approval_origin { |
||||||
|
font-weight: 999; |
||||||
|
margin-top: 16px; |
||||||
|
word-wrap: break-word; |
||||||
|
} |
Loading…
Reference in new issue