Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion lib/actions/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { createAction } from 'redux-actions'
import { routingQuery } from './api'
import { setQueryParam } from './form'
import { routeTo } from './ui'
import { TRIPS_PATH } from '../util/constants'
import { TRIPS_PATH, URL_ROOT } from '../util/constants'
import { secureFetch } from '../util/middleware'
import { isBlank } from '../util/ui'
import { isNewUser, positionHomeAndWorkFirst } from '../util/user'
Expand Down Expand Up @@ -188,6 +188,33 @@ export function createOrUpdateUser (userData, silentOnSuccess = false) {
}
}

/**
* Deletes a user (and their corresponding trips, requests, etc.) from the
* middleware database.
* @param userData the user account to delete
* @param auth0 auth0 object (gives access to logout function)
*/
export function deleteUser (userData, auth0) {
return async function (dispatch, getState) {
const { accessToken, apiBaseUrl, apiKey } = getMiddlewareVariables(getState())
const { id } = userData // Middleware ID, NOT auth0 (or similar) id.
const { data: deletedUser, message, status } = await secureFetch(
`${apiBaseUrl}${API_OTPUSER_PATH}/${id}`,
accessToken,
apiKey,
'DELETE'
)
// TODO: improve the UI feedback messages for this.
if (status === 'success' && deletedUser) {
alert(`Your user account (${userData.email}) has been deleted.`)
// Log out user and route them to the home page.
auth0.logout({returnTo: URL_ROOT})
} else {
alert(`An error was encountered:\n${JSON.stringify(message)}`)
}
}
}

/**
* Requests the verification email for the new user to be resent.
*/
Expand Down
23 changes: 23 additions & 0 deletions lib/components/user/delete-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react'
import { Button } from 'react-bootstrap'
import styled from 'styled-components'

const DeleteButton = styled(Button)`
background-color: white;
color: #d9534f;
:hover, :focus, :active, :focus:active {
background-color: #f7f7f7;
color: #d9534f;
}
`

/**
* Renders a delete user button for the account settings page.
*/
const DeleteUser = ({onDelete}) => (
<DeleteButton block bsSize='large' bsStyle='danger' onClick={onDelete}>
Delete my account
</DeleteButton>
)

export default DeleteUser
5 changes: 5 additions & 0 deletions lib/components/user/existing-account-display.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'

import DeleteUser from './delete-user'
import NotificationPrefsPane from './notification-prefs-pane'
import FavoritePlacesList from './places/favorite-places-list'
import StackedPaneDisplay from './stacked-pane-display'
Expand Down Expand Up @@ -29,6 +30,10 @@ const ExistingAccountDisplay = props => {
pane: TermsOfUsePane,
props: { ...props, disableCheckTerms: true },
title: 'Terms'
},
{
pane: DeleteUser,
props
}
]
return (
Expand Down
16 changes: 15 additions & 1 deletion lib/components/user/user-account-screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ class UserAccountScreen extends Component {
this._updateUserPrefs(userData, true)
}

_handleDeleteUser = (evt) => {
const {auth0, deleteUser, loggedInUser} = this.props
// Avoid triggering onsubmit with formik (which would result in a save user
// call).
evt.preventDefault()
if (confirm('Are you sure you would like to delete your user account? Once you do so, it cannot be recovered.')) {
deleteUser(loggedInUser, auth0)
}
}

_handleExit = () => {
// On exit, route to default search route.
this.props.routeTo('/')
Expand Down Expand Up @@ -96,7 +106,9 @@ class UserAccountScreen extends Component {
// We pass the Formik props below to the components rendered so that individual controls
// can be wired to be managed by Formik.
formikProps => {
const DisplayComponent = isCreating ? NewAccountWizard : ExistingAccountDisplay
const DisplayComponent = isCreating
? NewAccountWizard
: ExistingAccountDisplay

return (
<Form noValidate>
Expand All @@ -107,6 +119,7 @@ class UserAccountScreen extends Component {
loggedInUser={loggedInUser}
onCancel={this._handleExit}
onCreate={this._handleCreateNewUser}
onDelete={this._handleDeleteUser}
onRequestPhoneVerificationCode={requestPhoneVerificationSms}
onSendPhoneVerificationCode={verifyPhoneNumber}
phoneFormatOptions={phoneFormatOptions}
Expand Down Expand Up @@ -137,6 +150,7 @@ const mapStateToProps = (state, ownProps) => {

const mapDispatchToProps = {
createOrUpdateUser: userActions.createOrUpdateUser,
deleteUser: userActions.deleteUser,
requestPhoneVerificationSms: userActions.requestPhoneVerificationSms,
routeTo: uiActions.routeTo,
verifyPhoneNumber: userActions.verifyPhoneNumber
Expand Down