Skip to content

Commit

Permalink
Merge pull request #569 from ONEARMY/feat/user-profile-delete
Browse files Browse the repository at this point in the history
add profile delete methods and ui
  • Loading branch information
BenGamma authored Sep 12, 2019
2 parents 6cdc9cb + 2c4eedc commit 6a953ff
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 4 deletions.
12 changes: 9 additions & 3 deletions src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import styled from 'styled-components'

interface IProps {
// provide onDidDismiss function to enable backdrop click dismiss
onDidDismiss?: () => void
onDidDismiss: (data?: any) => void
height?: number
}
interface IState {
isOpen: boolean
Expand All @@ -27,7 +28,6 @@ const ModalContent = styled.div`
justify-content: space-between;
width: 300px;
max-width: 100%;
height: 200px;
max-height: 100%;
position: fixed;
z-index: 10;
Expand All @@ -51,13 +51,19 @@ export class Modal extends React.Component<IProps, IState> {

render() {
const isOpen = this.state
const { height, children } = this.props
return (
isOpen && (
<Portal id="portal">
<ModalBackdrop id="ModalBackdrop" onClick={() => this.dismiss()} />
<ModalContent id="ModalContent">{this.props.children}</ModalContent>
<ModalContent id="ModalContent" style={height ? { height } : {}}>
{children}
</ModalContent>
</Portal>
)
)
}
static defaultProps: IProps = {
onDidDismiss: () => null,
}
}
9 changes: 9 additions & 0 deletions src/pages/Settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Flex } from 'rebass'
import { Avatar } from 'src/components/Avatar'
import Text from 'src/components/Text'
import { UserMapPinEdit } from './content/UserMapPinEdit'
import { ProfileDelete } from './content/ProfileDelete'

interface IProps {
user: IUser
Expand All @@ -23,6 +24,7 @@ interface IState {
editMode: boolean
user: IUser
showNotification: boolean
showDeleteDialog?: boolean
}
export class UserSettings extends React.Component<IProps, IState> {
constructor(props: IProps) {
Expand All @@ -34,6 +36,10 @@ export class UserSettings extends React.Component<IProps, IState> {
this.setState({ showNotification: true })
}

public deleteProfile(reauthPw: string) {
this.props.userStore.deleteUser(reauthPw)
}

public render() {
const readOnly = !this.state.editMode

Expand Down Expand Up @@ -93,6 +99,9 @@ export class UserSettings extends React.Component<IProps, IState> {
/>
</div>
</BoxContainer>
<ProfileDelete
onConfirmation={reauthPw => this.deleteProfile(reauthPw)}
/>
</FlexContainer>
)
}
Expand Down
82 changes: 82 additions & 0 deletions src/pages/Settings/content/ProfileDelete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as React from 'react'
import { Modal } from 'src/components/Modal/Modal'
import { Button } from 'src/components/Button'
import Text from 'src/components/Text'
import { FlexContainer } from 'src/components/Layout/FlexContainer'
import { Form, Field } from 'react-final-form'
import { InputField } from 'src/components/Form/Fields'

interface IState {
showDeleteDialog: boolean
}
interface IProps {
onConfirmation: (reauthPw: string) => void
}
export class ProfileDelete extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props)
this.state = {
showDeleteDialog: false,
}
}
onModalDismiss(values: any) {
const reauthPw = values.password
this.setState({ showDeleteDialog: false })
if (reauthPw) {
this.props.onConfirmation(reauthPw)
}
}

render() {
return (
<>
<Button
icon="delete"
variant="light"
mt={3}
onClick={() => this.setState({ showDeleteDialog: true })}
>
Delete Profile
</Button>
{this.state.showDeleteDialog && (
<Modal onDidDismiss={confirm => this.onModalDismiss(confirm)}>
<Text>Confirm your password to delete your account</Text>
<Form
onSubmit={values => this.onModalDismiss(values)}
render={({ values, handleSubmit }) => {
return (
<form onSubmit={handleSubmit}>
<Field
name="password"
component={InputField}
type="password"
/>
<FlexContainer p={0}>
<Button
style={{ marginLeft: 'auto' }}
onClick={() => this.onModalDismiss({})}
>
Cancel
</Button>
<Button
type="submit"
variant={values.password ? 'light' : 'disabled'}
disabled={values.password ? false : true}
>
Delete
</Button>
</FlexContainer>
</form>
)
}}
/>
</Modal>
)}
</>
)
}

static defaultProps: IProps = {
onConfirmation: () => null,
}
}
2 changes: 1 addition & 1 deletion src/pages/common/Login/SignUp.form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class SignUpForm extends React.Component<IProps, IState> {

public async checkUserNameUnique(userName: string) {
const user = await this.props.userStore.getUserProfile(userName)
return user ? false : true
return user && !user._deleted ? false : true
}

public render = () => {
Expand Down
22 changes: 22 additions & 0 deletions src/stores/User/user.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,28 @@ export class UserStore {
return auth.signOut()
}


public async deleteUser(reauthPw: string) {
// as delete operation is sensitive requires user to revalidate credentials first
const authUser = auth.currentUser as firebase.User
const credential = EmailAuthProvider.credential(
authUser.email as string,
reauthPw,
)
try {
await authUser.reauthenticateAndRetrieveDataWithCredential(credential)
const user = this.user as IUser
await Database.deleteDoc(`v2_users/${user.userName}`)
await authUser.delete()
// TODO - delete user avatar
// TODO - show deleted notification
} catch (error) {
// TODO show notification if invalid credential
throw error
}
}


public async createUserProfile(fields: Partial<IUser> = {}) {
const authUser = auth.currentUser as firebase.User
const userName = authUser.displayName as string
Expand Down

0 comments on commit 6a953ff

Please sign in to comment.