Skip to content

Commit 13c9c6d

Browse files
authored
Version v1.5.0-alpha (#136)
### Description * Adds `updateProfile`, `updateAuth`, and `updateEmail` methods that dispatch associated start/success/failure actions * Adds multiple features to populate - #132 * Uses `prop-types` instead of importing from react - #122 * `distpatchOnUnsetListener` fixed to be `dispatchOnUnsetListener` (depreciation warning added along with a test confirm it is displayed) * Do not include `dbPath` in response from `deleteFile` method if it is undefined (test added to check this case) * `.eslintrc` file now using yaml format instead of JSON format (easier to read) * Unnessesary global eslint comments removed from tests (no longer needed due to globals being moved to `.eslintrc`) * `enableEmptyAuthChanges` config option added - #137 ### Check List - [X] All tests passing - [X] Docs updated with any changes or examples - [X] Added tests to ensure feature(s) work properly ### Relevant Issues * [#122](https://github.com/prescottprue/react-redux-firebase/issues/#122) * [#132](https://github.com/prescottprue/react-redux-firebase/issues/#132) * [#137](https://github.com/prescottprue/react-redux-firebase/issues/#137)
1 parent 451976a commit 13c9c6d

File tree

20 files changed

+478
-71
lines changed

20 files changed

+478
-71
lines changed

.eslintrc

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
{
2-
"parser" : "babel-eslint",
3-
"extends" : [
4-
"standard",
5-
"standard-react"
6-
],
7-
"plugins": [
8-
"babel"
9-
],
10-
"env" : {
11-
"browser" : true
12-
},
13-
"globals" : {
14-
"__DEV__" : false,
15-
"__PROD__" : false,
16-
"__DEBUG__" : false,
17-
"__COVERAGE__" : false,
18-
"__BASENAME__" : false
19-
},
20-
"rules": {
21-
"semi" : [2, "never"],
22-
"no-console": "error"
23-
}
24-
}
1+
root: true
2+
3+
parser: babel-eslint
4+
5+
extends: [standard, standard-react]
6+
plugins: [babel, react]
7+
8+
env:
9+
browser: true
10+
es6: true
11+
jasmine: true
12+
node: true
13+
14+
ecmaFeatures:
15+
jsx: true
16+
modules: true
17+
18+
globals:
19+
MockFirebase: true
20+
sinon: true
21+
Raven: true
22+
__COVERAGE__: true
23+
__DEV__: true
24+
25+
rules:
26+
semi: [2, 'never']
27+
no-console: 'error'

examples/complete/material/src/routes/Account/containers/AccountContainer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default class Account extends Component {
4242

4343
updateAccount = (newData) =>
4444
this.props.firebase
45-
.update(`${rfConfig.userProfile}/${this.props.auth.uid}`, newData)
45+
.updateProfile(newData)
4646
.catch((err) => {
4747
console.error('Error updating account', err) // eslint-disable-line no-console
4848
// TODO: Display error to user

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "react-redux-firebase",
3-
"version": "1.4.0",
3+
"version": "1.5.0-alpha",
44
"description": "Redux integration for Firebase. Comes with a Higher Order Component for use with React.",
55
"browser": "dist/react-redux-firebase.js",
66
"main": "lib/index.js",
77
"module": "es/index.js",
88
"jsnext:main": "es/index.js",
99
"scripts": {
1010
"clean": "rimraf dist",
11-
"lint": "eslint src/** test/**",
11+
"lint": "eslint src/** tests/**",
1212
"lint:fix": "npm run lint -- --fix",
1313
"test": "mocha -R spec --compilers js:babel-core/register ./tests/setup.js ./tests/**/*.spec.js",
1414
"test:cov": "istanbul cover ./node_modules/mocha/bin/_mocha -- ./tests/** --recursive --report lcov --compilers js:babel-register --require babel-polyfill",

src/actions/auth.js

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import {
1111
} from 'lodash'
1212
import jwtDecode from 'jwt-decode'
1313
import { actionTypes, defaultJWTProps } from '../constants'
14+
import { getLoginMethodAndParams } from '../utils/auth'
1415
import {
1516
promisesForPopulate,
1617
getPopulateObjs,
1718
getChildType
1819
} from '../utils/populate'
19-
import { getLoginMethodAndParams } from '../utils/auth'
2020

2121
const {
2222
SET,
@@ -242,6 +242,10 @@ export const init = (dispatch, firebase) => {
242242

243243
firebase.auth().onAuthStateChanged(authData => {
244244
if (!authData) {
245+
// Run onAuthStateChanged if it exists in config and enableEmptyAuthChanges is set to true
246+
if (isFunction(firebase._.config.onAuthStateChanged) && firebase._.config.enableEmptyAuthChanges) {
247+
firebase._.config.onAuthStateChanged(authData, firebase, dispatch)
248+
}
245249
return dispatch({ type: LOGOUT })
246250
}
247251

@@ -251,11 +255,12 @@ export const init = (dispatch, firebase) => {
251255
dispatchLogin(dispatch, authData)
252256

253257
// Run onAuthStateChanged if it exists in config
254-
if (firebase._.config.onAuthStateChanged) {
258+
if (isFunction(firebase._.config.onAuthStateChanged)) {
255259
firebase._.config.onAuthStateChanged(authData, firebase, dispatch)
256260
}
257261
})
258262

263+
// set redirect result callback if enableRedirectHandling set to true
259264
if (firebase._.config.enableRedirectHandling) {
260265
firebase.auth().getRedirectResult()
261266
.then((authData) => {
@@ -499,6 +504,122 @@ export const verifyPasswordResetCode = (dispatch, firebase, code) => {
499504
})
500505
}
501506

507+
/**
508+
* @description Update user profile
509+
* @param {Function} dispatch - Action dispatch function
510+
* @param {Object} firebase - Internal firebase object
511+
* @param {Object} userData - User data object (response from authenticating)
512+
* @param {Object} profile - Profile data to place in new profile
513+
* @return {Promise}
514+
* @private
515+
*/
516+
export const updateProfile = (dispatch, firebase, profileUpdate) => {
517+
const { database, _: { config, authUid } } = firebase
518+
dispatch({
519+
type: actionTypes.PROFILE_UPDATE_START,
520+
payload: profileUpdate
521+
})
522+
return database()
523+
.ref(`${config.userProfile}/${authUid}`)
524+
.update(profileUpdate)
525+
.then((snap) => {
526+
dispatch({
527+
type: actionTypes.PROFILE_UPDATE_SUCCESS,
528+
payload: snap.val()
529+
})
530+
})
531+
.catch((payload) => {
532+
dispatch({
533+
type: actionTypes.PROFILE_UPDATE_ERROR,
534+
payload
535+
})
536+
})
537+
}
538+
539+
/**
540+
* @description Update Auth Object. Internally calls
541+
* `firebase.auth().currentUser.updateProfile` as seen [in the firebase docs](https://firebase.google.com/docs/auth/web/manage-users#update_a_users_profile).
542+
* @param {Function} dispatch - Action dispatch function
543+
* @param {Object} firebase - Internal firebase object
544+
* @param {Object} profileUpdate - Update to be auth object
545+
* @return {Promise}
546+
* @private
547+
*/
548+
export const updateAuth = (dispatch, firebase, authUpdate, updateInProfile) => {
549+
dispatch({
550+
type: actionTypes.AUTH_UPDATE_START,
551+
payload: authUpdate
552+
})
553+
if (!firebase.auth().currentUser) {
554+
const msg = 'User must be logged in to update auth.'
555+
dispatch({
556+
type: actionTypes.AUTH_UPDATE_ERROR,
557+
payload: msg
558+
})
559+
return Promise.reject(msg)
560+
}
561+
return firebase.auth().currentUser
562+
.updateProfile(authUpdate)
563+
.then((payload) => {
564+
dispatch({
565+
type: actionTypes.AUTH_UPDATE_SUCCESS,
566+
payload: firebase.auth().currentUser
567+
})
568+
if (updateInProfile) {
569+
return updateProfile(dispatch, firebase, authUpdate)
570+
}
571+
return payload
572+
})
573+
.catch((payload) => {
574+
dispatch({
575+
type: actionTypes.AUTH_UPDATE_ERROR,
576+
payload
577+
})
578+
})
579+
}
580+
581+
/**
582+
* @description Update user's email. Internally calls
583+
* `firebase.auth().currentUser.updateEmail` as seen [in the firebase docs](https://firebase.google.com/docs/auth/web/manage-users#update_a_users_profile).
584+
* @param {Function} dispatch - Action dispatch function
585+
* @param {Object} firebase - Internal firebase object
586+
* @param {String} newEmail - Update to be auth object
587+
* @return {Promise}
588+
* @private
589+
*/
590+
export const updateEmail = (dispatch, firebase, newEmail, updateInProfile) => {
591+
dispatch({
592+
type: actionTypes.EMAIL_UPDATE_START,
593+
payload: newEmail
594+
})
595+
if (!firebase.auth().currentUser) {
596+
const msg = 'User must be logged in to update email.'
597+
dispatch({
598+
type: actionTypes.EMAIL_UPDATE_ERROR,
599+
payload: msg
600+
})
601+
return Promise.reject(msg)
602+
}
603+
return firebase.auth().currentUser
604+
.updateEmail(newEmail)
605+
.then((payload) => {
606+
dispatch({
607+
type: actionTypes.EMAIL_UPDATE_SUCCESS,
608+
payload: newEmail
609+
})
610+
if (updateInProfile) {
611+
return updateProfile(dispatch, firebase, { email: newEmail })
612+
}
613+
return payload
614+
})
615+
.catch((payload) => {
616+
dispatch({
617+
type: actionTypes.EMAIL_UPDATE_ERROR,
618+
payload
619+
})
620+
})
621+
}
622+
502623
export default {
503624
dispatchLoginError,
504625
dispatchUnauthorizedError,
@@ -512,5 +633,8 @@ export default {
512633
createUser,
513634
resetPassword,
514635
confirmPasswordReset,
515-
verifyPasswordResetCode
636+
verifyPasswordResetCode,
637+
updateAuth,
638+
updateProfile,
639+
updateEmail
516640
}

src/compose.js

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@ let firebaseInstance
3131
* auth redirect handling listener. (default: `true`)
3232
* @property {Function} config.onAuthStateChanged - Function run when auth state
3333
* changes. Argument Pattern: `(authData, firebase, dispatch)`
34+
* @property {Boolean} config.enableEmptyAuthChanges - Whether or not to enable
35+
* empty auth changes. When set to true, `onAuthStateChanged` will be fired with,
36+
* empty auth changes such as undefined on initialization. See
37+
* [#137](https://github.com/prescottprue/react-redux-firebase/issues/137) for
38+
* more details. (default: `false`)
3439
* @property {Function} config.onRedirectResult - Function run when redirect
3540
* result is returned. Argument Pattern: `(authData, firebase, dispatch)`
3641
* @property {Object} config.customAuthParameters - Object for setting which
3742
* customAuthParameters are passed to external auth providers.
38-
* @property {Function} config.profileFactory - Factory for modifying how user profile is saved.
43+
* @property {Function} config.profileFactory - Factory for modifying how user
44+
* profile is saved.
3945
* @property {Function} config.uploadFileDataFactory - Factory for modifying
4046
* how file meta data is written during file uploads
4147
* @property {Array|String} config.profileParamsToPopulate - Parameters within
@@ -411,11 +417,44 @@ export default (fbConfig, otherConfig) => next =>
411417
const verifyPasswordResetCode = (code) =>
412418
authActions.verifyPasswordResetCode(dispatch, instance, code)
413419

420+
/**
421+
* @description Update the currently logged in user's profile object
422+
* @param {String} profileUpdate - Changes to apply to profile
423+
* @return {Promise}
424+
*/
425+
const updateProfile = (profile) =>
426+
authActions.updateProfile(dispatch, instance, profile)
427+
428+
/**
429+
* @description Update the currently logged in user's auth object. **Note**:
430+
* changes Auth object **only**, not user's profile.
431+
* @param {String} code - Password reset code to verify
432+
* @return {Promise}
433+
*/
434+
const updateAuth = (authUpdate) =>
435+
authActions.updateAuth(dispatch, instance, authUpdate)
436+
437+
/**
438+
* @description Update the currently logged in user's email. **Note**:
439+
* changes email in Auth object only, not within user's profile.
440+
* @param {String} newEmail - New email
441+
* @param {Boolean} updateInProfile - Whether or not to update user's
442+
* profile with email change.
443+
* @return {Promise}
444+
*/
445+
const updateEmail = (email, updateInProfile) =>
446+
authActions.updateEmail(dispatch, instance, email, updateInProfile)
447+
414448
/**
415449
* @name ref
416450
* @description Firebase ref function
417451
* @return {database.Reference}
418452
*/
453+
/**
454+
* @name auth
455+
* @description Firebase auth service instance including all Firebase auth methods
456+
* @return {Auth}
457+
*/
419458
/**
420459
* @name database
421460
* @description Firebase database service instance including all Firebase storage methods
@@ -427,9 +466,9 @@ export default (fbConfig, otherConfig) => next =>
427466
* @return {Storage} Firebase storage service
428467
*/
429468
/**
430-
* @name auth
431-
* @description Firebase auth service instance including all Firebase auth methods
432-
* @return {Auth}
469+
* @name messaging
470+
* @description Firebase messaging service instance including all Firebase messaging methods
471+
* @return {Messaging} Firebase messaging service
433472
*/
434473
firebase.helpers = {
435474
ref: path => firebase.database().ref(path),
@@ -452,9 +491,11 @@ export default (fbConfig, otherConfig) => next =>
452491
verifyPasswordResetCode,
453492
watchEvent,
454493
unWatchEvent,
494+
updateProfile,
495+
updateAuth,
496+
updateEmail,
455497
storage: (app) => firebase.storage(app),
456-
messaging: (app) => firebase.messaging(app),
457-
instance: firebase
498+
messaging: (app) => firebase.messaging(app)
458499
}
459500

460501
authActions.init(dispatch, instance)

0 commit comments

Comments
 (0)