[Feature Request] User account confirmation (#23)

This commit is contained in:
Qolzam
2017-11-16 11:44:45 +07:00
parent 55789967eb
commit f64b7bb24d
26 changed files with 571 additions and 231 deletions

5
.firebaserc Normal file
View File

@@ -0,0 +1,5 @@
{
"projects": {
"default": "love-social"
}
}

3
.gitignore vendored
View File

@@ -4,5 +4,4 @@ config/
.vscode/
src/data/awsClient
src/components/AWS.tsx
.firebaserc
firebase.json
npm-debug.log

9
firebase.json Normal file
View File

@@ -0,0 +1,9 @@
{
"hosting": {
"public": "public",
"rewrites": [{
"source": "**",
"destination": "/index.html"
}]
}
}

View File

@@ -34,7 +34,7 @@ export const dbLogin = (email: string, password: string) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.login(email, password).then((result) => {
dispatch(globalActions.showNotificationSuccess())
dispatch(login(result.uid))
dispatch(login(result.uid,result.emailVerified))
dispatch(push('/'))
}, (error: SocialError) => dispatch(globalActions.showErrorMessage(error.code)))
}
@@ -71,7 +71,8 @@ export const dbSignup = (user: UserRegisterModel) => {
userId: result.uid,
...user
}))
dispatch(push('/'))
dispatch(dbSendEmailVerfication())
dispatch(push('/emailVerification'))
})
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.code)))
}
@@ -129,16 +130,36 @@ export const dbResetPassword = (email: string) => {
}
}
/**
* Send email verification
*/
export const dbSendEmailVerfication = () => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.sendEmailVerification().then(() => {
// Send email verification successful.
dispatch(globalActions.showNotificationSuccess())
dispatch(push('/'))
})
.catch((error: SocialError) => {
// An error happened.
dispatch(globalActions.showErrorMessage(error.code))
})
}
}
/* _____________ CRUD State _____________ */
/**
* Loing user
* @param {string} uids
*/
export const login = (uid: string) => {
export const login = (uid: string, isVerifide: boolean) => {
return {
type: AuthorizeActionType.LOGIN,
payload: { authed: true, uid }
payload: { authed: true, isVerifide, uid }
}
}

View File

@@ -0,0 +1,132 @@
// - Import external components
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { NavLink, withRouter } from 'react-router-dom'
import { push } from 'react-router-redux'
import Paper from 'material-ui/Paper'
import TextField from 'material-ui/TextField'
import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton'
import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
// - Import actions
import * as authorizeActions from 'actions/authorizeActions'
import { IEmailVerificationComponentProps } from './IEmailVerificationComponentProps'
import { IEmailVerificationComponentState } from './IEmailVerificationComponentState'
/**
* Create component class
*
* @export
* @class EmailVerificationComponent
* @extends {Component}
*/
export class EmailVerificationComponent extends Component<IEmailVerificationComponentProps,IEmailVerificationComponentState> {
styles = {
message: {
fontWeight: 100
},
sendButton: {
marginTop: 60
}
}
/**
* Component constructor
* @param {object} props is an object properties of component
*/
constructor (props: IEmailVerificationComponentProps) {
super(props)
// Binding function to `this`
}
/**
* Reneder component DOM
* @return {react element} return the DOM which rendered by component
*/
render () {
const paperStyle = {
minHeight: 370,
width: 450,
textAlign: 'center',
display: 'block',
margin: 'auto'
}
return (
<div>
<h1 style={{
textAlign: 'center',
padding: '20px',
fontSize: '30px',
fontWeight: 500,
lineHeight: '32px',
margin: 'auto',
color: 'rgba(138, 148, 138, 0.2)'
}}>Green</h1>
<div className='animate-bottom'>
<Paper style={paperStyle} zDepth={1} rounded={false} >
<div style={{ padding: '48px 40px 36px' }}>
<div style={{
paddingLeft: '40px',
paddingRight: '40px'
}}>
<h2 style={{
textAlign: 'left',
paddingTop: '16px',
fontSize: '24px',
fontWeight: 400,
lineHeight: '32px',
margin: 0
}} className='zoomOutLCorner animated'>Email Verification</h2>
</div>
<p style={this.styles.message as any}>
An verificiation email has been already sent to you. Please check your inbox. If you couldn't see the emai, please resend email verification.
</p>
<div style={this.styles.sendButton}>
<RaisedButton label='Send Email Verification' primary={true} onClick={() => this.props.sendEmailVerification()} />
</div>
</div>
</Paper>
</div>
</div>
)
}
}
/**
* Map dispatch to props
* @param {func} dispatch is the function to dispatch action to reducers
* @param {object} ownProps is the props belong to component
* @return {object} props of component
*/
const mapDispatchToProps = (dispatch: Function, ownProps: IEmailVerificationComponentProps) => {
return {
loginPage: () => {
dispatch(push('/login'))
},
sendEmailVerification: () => dispatch(authorizeActions.dbSendEmailVerfication())
}
}
/**
* Map state to props
* @param {object} state is the obeject from redux store
* @param {object} ownProps is the props belong to component
* @return {object} props of component
*/
const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps) => {
return {
}
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(EmailVerificationComponent as any))

View File

@@ -0,0 +1,4 @@
export interface IEmailVerificationComponentProps {
sendEmailVerification: () => any
}

View File

@@ -0,0 +1,5 @@
export interface IEmailVerificationComponentState {
}

View File

@@ -0,0 +1,2 @@
import EmailVerificationComponent from './EmailVerificationComponent'
export default EmailVerificationComponent

View File

@@ -28,7 +28,18 @@ import People from 'components/people'
import CircleAPI from 'api/CircleAPI'
// - Import actions
import * as globalActions from 'actions/globalActions'
// - Import actions
import {
authorizeActions,
imageGalleryActions,
postActions,
commentActions,
voteActions,
userActions,
globalActions,
circleActions,
notifyActions
} from 'actions'
import { IHomeComponentProps } from './IHomeComponentProps'
import { IHomeComponentState } from './IHomeComponentState'
@@ -93,6 +104,24 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
})
}
componentWillMount () {
const {global, clearData, loadData, authed, defaultDataEnable, isVerifide, goTo } = this.props
if (!authed) {
goTo!('/login')
return
}
if (!isVerifide) {
goTo!('/emailVerification')
} else if (!global.defaultLoadDataStatus) {
clearData!()
loadData!()
defaultDataEnable!()
}
}
/**
* Render DOM component
*
@@ -101,7 +130,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
* @memberof Home
*/
render () {
const {loaded} = this.props
return (
<div id='home'>
<HomeHeader sidebar={this.state.sidebarOpen} sidebarStatus={this.state.sidebarStatus} />
@@ -123,7 +152,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
</SidebarContent>
<SidebarMain>
<Switch>
{loaded ? (<Switch>
<Route path='/people/:tab?' render={() => {
return (
this.props.authed
@@ -150,7 +179,8 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
: <Redirect to='/login' />
)
}} />
</Switch>
</Switch>)
: ''}
</SidebarMain>
</Sidebar>
@@ -160,16 +190,40 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
}
}
/**
* Map dispatch to props
* @param {func} dispatch is the function to dispatch action to reducers
* @param {object} ownProps is the props belong to component
* @return {object} props of component
*/
// - Map dispatch to props
const mapDispatchToProps = (dispatch: any, ownProps: IHomeComponentProps) => {
return {
return {
loadData: () => {
dispatch(commentActions.dbGetComments())
dispatch(imageGalleryActions.dbGetImageGallery())
dispatch(postActions.dbGetPosts())
dispatch(userActions.dbGetUserInfo())
dispatch(voteActions.dbGetVotes())
dispatch(notifyActions.dbGetNotifications())
dispatch(circleActions.dbGetCircles())
},
clearData: () => {
dispatch(imageGalleryActions.clearAllData())
dispatch(postActions.clearAllData())
dispatch(userActions.clearAllData())
dispatch(commentActions.clearAllData())
dispatch(voteActions.clearAllvotes())
dispatch(notifyActions.clearAllNotifications())
dispatch(circleActions.clearAllCircles())
dispatch(globalActions.clearTemp())
},
defaultDataDisable: () => {
dispatch(globalActions.defaultDataDisable())
},
defaultDataEnable: () => {
dispatch(globalActions.defaultDataEnable())
},
goTo: (url: string) => dispatch(push(url))
}
}
/**
@@ -179,20 +233,24 @@ const mapDispatchToProps = (dispatch: any, ownProps: IHomeComponentProps) => {
* @return {object} props of component
*/
const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
const { uid } = state.authorize
const { authorize, global, user, post, comment, imageGallery, vote, notify, circle } = state
const { uid } = authorize
let mergedPosts = {}
const circles = state.circle ? (state.circle.userCircles[uid] || {}) : {}
const circles = circle ? (circle.userCircles[uid] || {}) : {}
const followingUsers = CircleAPI.getFollowingUsers(circles)
const posts = state.post.userPosts ? state.post.userPosts[state.authorize.uid] : {}
const posts = post.userPosts ? post.userPosts[authorize.uid] : {}
Object.keys(followingUsers).forEach((userId) => {
let newPosts = state.post.userPosts ? state.post.userPosts[userId] : {}
let newPosts = post.userPosts ? post.userPosts[userId] : {}
_.merge(mergedPosts,newPosts)
})
_.merge(mergedPosts,posts)
return {
authed: state.authorize.authed,
mainStyle: state.global.sidebarMainStyle,
mergedPosts
authed: authorize.authed,
isVerifide: authorize.isVerifide,
mainStyle: global.sidebarMainStyle,
mergedPosts,
global,
loaded: user.loaded && post.loaded && comment.loaded && imageGallery.loaded && vote.loaded && notify.loaded && circle.loaded
}
}

View File

@@ -10,6 +10,14 @@ export interface IHomeComponentProps {
*/
authed?: boolean
/**
* If user email is verifide {true} or not {false}
*
* @type {boolean}
* @memberof IHomeComponentProps
*/
isVerifide?: boolean
/**
* User identifier
*
@@ -25,4 +33,59 @@ export interface IHomeComponentProps {
* @memberof IHomeComponentProps
*/
mergedPosts?: {[postId: string]: Post}
/**
* Global state
*
* @type {*}
* @memberof IMasterProps
*/
global?: any
/**
* Clear user date from store
*
* @type {Function}
* @memberof IMasterProps
*/
clearData?: Function
/**
* Set flag {true} which all user data has loaded
*
* @type {Function}
* @memberof IMasterProps
*/
defaultDataEnable?: Function
/**
* Load user data into store
*
* @type {Function}
* @memberof IMasterProps
*/
loadData?: Function
/**
* Set flag {false} which user data has not loaded
*
* @type {Function}
* @memberof IMasterProps
*/
defaultDataDisable?: Function
/**
* Redirect to [url]
*
* @memberof IHomeComponentProps
*/
goTo?: (url: string) => any
/**
* If all requierment data loaded {true} or not {false}
*
* @type {boolean}
* @memberof IHomeComponentProps
*/
loaded?: boolean
}

View File

@@ -1,3 +1,4 @@
import { User } from 'core/domain/users';
export interface IMasterComponentProps {
/**
* Close gloal message
@@ -5,91 +6,91 @@ export interface IMasterComponentProps {
* @type {Function}
* @memberof IMasterProps
*/
closeMessage: Function,
closeMessage: Function
/**
* Show progress bar information
*
* @type {*}
* @memberof IMasterProps
*/
progress: any,
progress: any
/**
* Login a user
*
* @type {Function}
* @memberof IMasterProps
*/
login: Function,
login: (userId: string, isVerifide: boolean) => any
/**
* Global state
*
* @type {*}
* @memberof IMasterProps
*/
global: any,
global: any
/**
* Set flag {false} which user data has not loaded
*
* @type {Function}
* @memberof IMasterProps
*/
defaultDataDisable: Function,
defaultDataDisable: Function
/**
* Logout current user
*
* @type {Function}
* @memberof IMasterProps
*/
logout: Function,
logout: Function
/**
* Clear user date from store
*
* @type {Function}
* @memberof IMasterProps
*/
clearData: Function,
clearData: Function
/**
* Prepare default data for a guest user
*
* @type {Function}
* @memberof IMasterProps
*/
loadDataGuest: Function,
loadDataGuest: Function
/**
* Set flag {true} which all user data has loaded
*
* @type {Function}
* @memberof IMasterProps
*/
defaultDataEnable: Function,
defaultDataEnable: Function
/**
* Load user data into store
*
* @type {Function}
* @memberof IMasterProps
*/
loadData: Function,
loadData: Function
/**
* If all data from all entities are loaded {true} if not {false}
*
* @type {Boolean}
* @memberof IMasterProps
*/
loaded: Boolean,
loaded: Boolean
/**
* If current user is guest {true} if no
*
* @type {Boolean}
* @memberof IMasterProps
*/
guest: Boolean,
guest: Boolean
/**
* If current user is authed {true} if not {false}
*
* @type {Boolean}
* @memberof IMasterProps
*/
authed: Boolean,
authed: Boolean
/**
* Authed user identifier
*

View File

@@ -21,4 +21,12 @@ export interface IMasterComponentState {
* @memberof IMasterState
*/
dataLoaded: boolean
/**
* If user verifide it's email {true} or not {false}
*
* @type {boolean}
* @memberof IMasterComponentState
*/
isVerifide: boolean
}

View File

@@ -10,6 +10,7 @@ import LinearProgress from 'material-ui/LinearProgress'
// - Import components
import Home from 'components/home'
import Signup from 'components/signup'
import EmailVerification from 'components/emailVerification'
import Login from 'components/login'
import ResetPassword from 'components/resetPassword'
import Setting from 'components/setting'
@@ -50,7 +51,8 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
this.state = {
loading: true,
authed: false,
dataLoaded: false
dataLoaded: false,
isVerifide: false
}
// Binding functions to `this`
@@ -81,28 +83,26 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
componentWillMount () {
this._authourizeService.onAuthStateChanged((user: any) => {
this._authourizeService.onAuthStateChanged((isVerifide: boolean, user: any) => {
const {global, clearData, loadDataGuest, defaultDataDisable, defaultDataEnable, login, logout } = this.props
if (user) {
this.props.login(user)
login(user.uid,isVerifide)
this.setState({
loading: false
loading: false,
isVerifide: true
})
if (!this.props.global.defaultLoadDataStatus) {
this.props.clearData()
this.props.loadData()
this.props.defaultDataEnable()
}
} else {
this.props.logout()
logout()
this.setState({
loading: false
loading: false,
isVerifide: false
})
if (this.props.global.defaultLoadDataStatus) {
this.props.defaultDataDisable()
this.props.clearData()
if (global.defaultLoadDataStatus) {
defaultDataDisable()
clearData()
}
this.props.loadDataGuest()
loadDataGuest()
}
})
@@ -117,7 +117,8 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
*/
public render (): React.ReactElement<{}> {
const { progress, global } = this.props
const { progress, global, loaded, guest } = this.props
const { loading, isVerifide } = this.state
return (
<div id='master'>
@@ -128,25 +129,25 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
<div className='master__loading animate-fading2' style={{ display: (global.showTopLoading ? 'flex' : 'none') }}>
<div className='title'>Loading ... </div>
</div>
<MasterLoading activeLoading={this.state.loading || !(this.props.loaded || this.props.guest)} handleLoading={this.handleLoading} />
<MasterLoading activeLoading={loading} handleLoading={this.handleLoading} />
{(!this.state.loading && (this.props.loaded || this.props.guest))
? (<Switch>
<Route path='/signup' component={Signup} />
<Route path='/settings' component={Setting} />
<Route path='/resetPassword' component={ResetPassword} />
<Route path='/login' render={() => {
console.log('this.props.authed: ', this.props.authed, 'this.props: ', this.props)
return (
this.props.authed
? <Redirect to='/' />
: <Login />
)
}
} />
<Route render={() => <Home uid={this.props.uid} />} />
{(!loading) ? (<Switch>
<Route path='/signup' component={Signup} />
<Route path='/emailVerification' component={EmailVerification} />
<Route path='/settings' component={Setting} />
<Route path='/resetPassword' component={ResetPassword} />
<Route path='/login' render={() => {
return (
this.props.authed
? <Redirect to='/' />
: <Login />
)
}
} />
<Route render={() => <Home uid={this.props.uid} />} />
</Switch>) : ''
</Switch>)
: ''
}
<Snackbar
open={this.props.global.messageOpen}
@@ -164,16 +165,6 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
const mapDispatchToProps = (dispatch: any, ownProps: IMasterComponentProps) => {
return {
loadData: () => {
dispatch(commentActions.dbGetComments())
dispatch(imageGalleryActions.dbGetImageGallery())
dispatch(postActions.dbGetPosts())
dispatch(userActions.dbGetUserInfo())
dispatch(voteActions.dbGetVotes())
dispatch(notifyActions.dbGetNotifications())
dispatch(circleActions.dbGetCircles())
},
clearData: () => {
dispatch(imageGalleryActions.clearAllData())
dispatch(postActions.clearAllData())
@@ -185,8 +176,8 @@ const mapDispatchToProps = (dispatch: any, ownProps: IMasterComponentProps) => {
dispatch(globalActions.clearTemp())
},
login: (user: any) => {
dispatch(authorizeActions.login(user.uid))
login: (userId: string, isVerifide: boolean) => {
dispatch(authorizeActions.login(userId, isVerifide))
},
logout: () => {
dispatch(authorizeActions.logout())
@@ -218,8 +209,7 @@ const mapStateToProps = (state: any) => {
uid: authorize.uid,
authed: authorize.authed,
progress: global.progress,
global: global,
loaded: user.loaded && post.loaded && comment.loaded && imageGallery.loaded && vote.loaded && notify.loaded && circle.loaded
global: global
}
}

View File

@@ -0,0 +1,16 @@
export interface IResetPasswordComponentProps {
/**
* Reset password
*
* @memberof IResetPasswordComponentProps
*/
resetPassword?: (email: string) => any
/**
* Redirect to login page
*
* @memberof IResetPasswordComponentProps
*/
loginPage?: () => void
}

View File

@@ -1,11 +1,11 @@
export interface IRestPasswordComponentState {
export interface IResetPasswordComponentState {
/**
* Email input value
*
* @type {string}
* @memberof IRestPasswordComponentState
* @memberof IResetPasswordComponentState
*/
emailInput: string
@@ -13,7 +13,7 @@ export interface IRestPasswordComponentState {
* Email input error text
*
* @type {string}
* @memberof IRestPasswordComponentState
* @memberof IResetPasswordComponentState
*/
emailInputError: string

View File

@@ -1,16 +0,0 @@
export interface IRestPasswordComponentProps {
/**
* Reset password
*
* @memberof IRestPasswordComponentProps
*/
resetPassword: (email: string) => any
/**
* Redirect to login page
*
* @memberof IRestPasswordComponentProps
*/
loginPage: () => void
}

View File

@@ -11,23 +11,23 @@ import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
// - Import actions
import * as authorizeActions from 'actions/authorizeActions'
import { IRestPasswordComponentProps } from './IRestPasswordComponentProps'
import { IRestPasswordComponentState } from './IRestPasswordComponentState'
import { IResetPasswordComponentProps } from './IResetPasswordComponentProps'
import { IResetPasswordComponentState } from './IResetPasswordComponentState'
/**
* Create component class
*
* @export
* @class RestPasswordComponent
* @class ResetPasswordComponent
* @extends {Component}
*/
export class RestPasswordComponent extends Component<IRestPasswordComponentProps,IRestPasswordComponentState> {
export class ResetPasswordComponent extends Component<IResetPasswordComponentProps,IResetPasswordComponentState> {
/**
* Component constructor
* @param {object} props is an object properties of component
*/
constructor (props: IRestPasswordComponentProps) {
constructor (props: IResetPasswordComponentProps) {
super(props)
this.state = {
@@ -68,7 +68,7 @@ export class RestPasswordComponent extends Component<IRestPasswordComponentProps
return
}
this.props.resetPassword(this.state.emailInput)
this.props.resetPassword!(this.state.emailInput)
}
/**
@@ -148,7 +148,7 @@ export class RestPasswordComponent extends Component<IRestPasswordComponentProps
* @param {object} ownProps is the props belong to component
* @return {object} props of component
*/
const mapDispatchToProps = (dispatch: Function, ownProps: IRestPasswordComponentProps) => {
const mapDispatchToProps = (dispatch: Function, ownProps: IResetPasswordComponentProps) => {
return {
loginPage: () => {
dispatch(push('/login'))
@@ -163,11 +163,11 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IRestPasswordComponent
* @param {object} ownProps is the props belong to component
* @return {object} props of component
*/
const mapStateToProps = (state: any, ownProps: IRestPasswordComponentProps) => {
const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) => {
return {
}
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(RestPasswordComponent as any))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ResetPasswordComponent as any))

View File

@@ -1,2 +1,2 @@
import RestPasswordComponent from './RestPasswordComponent'
export default RestPasswordComponent
import ResetPasswordComponent from './ResetPasswordComponent'
export default ResetPasswordComponent

View File

@@ -1,25 +1,23 @@
import { BaseDomain } from 'core/domain/common'
export class LoginUser extends BaseDomain{
export class LoginUser extends BaseDomain {
constructor(uid: string){
super()
constructor (private _uid: string, private _emailVerified: boolean) {
super()
}
this._uid = uid
}
/**
* User identifier
*
*
* @type {string}
* @memberof LoginUser
*/
private _uid : string
public get uid() : string {
return this._uid
}
public get uid (): string {
return this._uid
}
public get emailVerified (): boolean {
return this._emailVerified
}
}
}

View File

@@ -1,4 +1,10 @@
export class SocialError {
export class SocialError extends Error {
private _isError: Boolean
constructor (private _code: string, private _message: string) {
super(_message)
this._isError = true
}
/**
* Error code
*
@@ -26,13 +32,8 @@ export class SocialError {
* @memberof SocialError
*/
private _isError: Boolean
public get isError (): Boolean {
return this._isError
}
constructor (private _code: string, private _message: string) {
this._isError = true
}
}

View File

@@ -40,7 +40,7 @@ export interface IAuthorizeService {
*
* @memberof IAuthorizeService
*/
onAuthStateChanged: (callBack: (user: User) => void) => void
onAuthStateChanged: (callBack: (isVerifide: boolean, user: User) => void) => void
/**
* Reset user password
@@ -48,4 +48,11 @@ export interface IAuthorizeService {
* @memberof IAuthorizeService
*/
resetPassword: (email: string) => Promise<void>
/**
* Send email verification
*
* @memberof IAuthorizeService
*/
sendEmailVerification: () => Promise<void>
}

View File

@@ -27,7 +27,7 @@ export class AuthorizeService implements IAuthorizeService {
firebaseAuth()
.signInWithEmailAndPassword(email, password)
.then((result) => {
resolve(new LoginUser(result.uid))
resolve(new LoginUser(result.uid, result.emailVerified))
})
.catch((error: any) => {
reject(new SocialError(error.code, error.message))
@@ -108,8 +108,18 @@ export class AuthorizeService implements IAuthorizeService {
*
* @memberof IAuthorizeService
*/
public onAuthStateChanged: (callBack: (user: User) => void) => any = (callBack) => {
firebaseAuth().onAuthStateChanged(callBack)
public onAuthStateChanged: (callBack: (isVerifide: boolean, user: User) => void) => any = (callBack) => {
firebaseAuth().onAuthStateChanged( (user: any) => {
let isVerifide = false
if (user) {
if (user.emailVerified) {
isVerifide = true
} else {
isVerifide = false
}
}
callBack(isVerifide,user)
})
}
/**
@@ -129,4 +139,23 @@ export class AuthorizeService implements IAuthorizeService {
})
})
}
public sendEmailVerification: () => Promise<void> = () => {
return new Promise<void>((resolve,reject) => {
let auth = firebaseAuth()
const user = auth.currentUser
if (user) {
user.sendEmailVerification().then(() => {
resolve()
}).catch((error: any) => {
// An error happened.
reject(new SocialError(error.code, error.message))
})
} else {
reject(new SocialError('nullException', 'User was null'));
}
})
}
}

View File

@@ -1,40 +1,48 @@
/**
* Post state
*
* Post state
*
* @export
* @class AuthorizeState
*/
export class AuthorizeState {
export class AuthorizeState {
/**
* Authorized user identifier
*
*
* @type {number}
* @memberof AuthorizeState
*/
uid: number = 0
uid: number = 0
/**
* If user is authed {true} or not {false}
*
*
* @type {Boolean}
* @memberof AuthorizeState
*/
authed: Boolean = false
authed: Boolean = false
/**
* If user is verifide {true} or not {false}
*
* @type {Boolean}
* @memberof AuthorizeState
*/
isVerfide: Boolean = false
/**
* If user password is updated {true} or not {false}
*
*
* @type {Boolean}
* @memberof AuthorizeState
*/
updatePassword: Boolean = false
updatePassword: Boolean = false
/**
* If the user is guest {true} or not {false}
*
*
* @type {Boolean}
* @memberof AuthorizeState
*/
guest: Boolean = false
}
guest: Boolean = false
}

View File

@@ -1,15 +1,14 @@
// - Import action types
import {AuthorizeActionType} from 'constants/authorizeActionType'
import { AuthorizeActionType } from 'constants/authorizeActionType'
/**
* Authorize action interface
*
*
* @export
* @interface IAuthorizeAction
*/
export interface IAuthorizeAction {
payload: any
type: AuthorizeActionType
}
export interface IAuthorizeAction {
payload: any
type: AuthorizeActionType
}

View File

@@ -20,7 +20,8 @@ export let authorizeReducer = (state: AuthorizeState = new AuthorizeState(), act
...state,
uid: payload.uid,
authed: true,
guest: false
guest: false,
isVerifide: payload.isVerifide
}
case AuthorizeActionType.LOGOUT:
return{

View File

@@ -6,101 +6,101 @@
*/
export class GlobalState {
/**
* Set percent of loading progress and visibility for Master component
*
* @type {{
* percent: number,
* visible: Boolean
* }}
* @memberof IGlobalState
*/
/**
* Set percent of loading progress and visibility for Master component
*
* @type {{
* percent: number,
* visible: Boolean
* }}
* @memberof IGlobalState
*/
progress: {
percent: number
visible: Boolean
} = {
percent : 0,
visible : false
percent: 0,
visible: false
}
/**
* If loading is enabled {true} or not false
*
* @type {Boolean}
* @memberof IGlobalState
*/
/**
* If loading is enabled {true} or not false
*
* @type {Boolean}
* @memberof IGlobalState
*/
loadingStatus: Boolean = true
/**
* If user date is loaded {true} or not {false}
*
* @type {Boolean}
* @memberof IGlobalState
*/
/**
* If user date is loaded {true} or not {false}
*
* @type {Boolean}
* @memberof IGlobalState
*/
defaultLoadDataStatus: Boolean = false
/**
* If message popup is open {true} or not {false}
*
* @type {Boolean}
* @memberof IGlobalState
*/
/**
* If message popup is open {true} or not {false}
*
* @type {Boolean}
* @memberof IGlobalState
*/
messageOpen: Boolean = false
/**
* The text of popup global message
*
* @type {string}
* @memberof IGlobalState
*/
/**
* The text of popup global message
*
* @type {string}
* @memberof IGlobalState
*/
message: string = ''
/**
* Window size
*
* @type {number}
* @memberof IGlobalState
*/
/**
* Window size
*
* @type {number}
* @memberof IGlobalState
*/
windowWidth: number = 0
/**
* Window height
*
* @type {number}
* @memberof IGlobalState
*/
/**
* Window height
*
* @type {number}
* @memberof IGlobalState
*/
windowHeight: number = 0
/**
* The text of website header
*
* @type {string}
* @memberof IGlobalState
*/
/**
* The text of website header
*
* @type {string}
* @memberof IGlobalState
*/
headerTitle: string = ''
/**
* Top loading is visible {true} or not {false}
*
* @type {Boolean}
* @memberof IGlobalState
*/
/**
* Top loading is visible {true} or not {false}
*
* @type {Boolean}
* @memberof IGlobalState
*/
showTopLoading: Boolean = false
/**
* Top loading message queue
*
* @type {number}
* @memberof IGlobalState
*/
/**
* Top loading message queue
*
* @type {number}
* @memberof IGlobalState
*/
topLoadingQueue: number = 0
/**
* Temp date storage
*
* @type {*}
* @memberof IGlobalState
*/
/**
* Temp date storage
*
* @type {*}
* @memberof IGlobalState
*/
temp: any = {
caller: []
}