From c004904b196c54668c7066adb1b6f4d4c282ecaf Mon Sep 17 00:00:00 2001 From: Idan Entin Date: Tue, 23 May 2017 23:51:43 +0300 Subject: [PATCH] feat(auth): Add ability to link user with email credentials to current user --- src/auth/FirebaseAuth.js | 21 ++++++++ tests/unit/FirebaseAuth.spec.js | 89 +++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/src/auth/FirebaseAuth.js b/src/auth/FirebaseAuth.js index 1b30251e..b2266118 100644 --- a/src/auth/FirebaseAuth.js +++ b/src/auth/FirebaseAuth.js @@ -59,6 +59,7 @@ $updateEmail: this.updateEmail.bind(this), $deleteUser: this.deleteUser.bind(this), $sendPasswordResetEmail: this.sendPasswordResetEmail.bind(this), + $linkUser: this.linkUser.bind(this), // Hack: needed for tests _: this @@ -334,6 +335,26 @@ } }, + /** + * Links the currently logged in user to a user with the given credentials. + * + * @param {string} email User's email + * @param {string} password User's password + * @return {Promise} A promise fulfilled with the `firebase.User` object. + */ + linkUser: function(email, password) { + var user = this.getAuth(), + credential; + + if (!user) { + throw new Error('No user to link to (user must login before linking)'); + } + + credential = firebase.auth.EmailAuthProvider.credential(email, password); + + return user.link(credential); + }, + /** * Sends a password reset email to an email/password user. diff --git a/tests/unit/FirebaseAuth.spec.js b/tests/unit/FirebaseAuth.spec.js index 4f524d32..5c4ded9f 100644 --- a/tests/unit/FirebaseAuth.spec.js +++ b/tests/unit/FirebaseAuth.spec.js @@ -681,4 +681,93 @@ describe('FirebaseAuth',function(){ expect(result).toEqual('myResult'); }); }); + + describe('$linkUser()',function (){ + it('should return a promise', function () { + var email = 'somebody@somewhere.com'; + var password = 'myPass'; + var credentials = { + provider: 'password', + uid: 'testUid', + link: jasmine.createSpy().and.returnValue(fakePromise()) + }; + spyOn(authService._, 'getAuth').and.returnValue(credentials); + + expect(authService.$linkUser(email, password)).toBeAPromise(); + }); + + it('should pass email and password to method on backing auth instance', function () { + var email = 'somebody@somewhere.com', + password = 'myPass'; + var credentials = { + provider: 'password', + uid: 'testUid', + link: jasmine.createSpy().and.returnValue(fakePromise()) + }; + spyOn(authService._, 'getAuth').and.callFake(function () { + return credentials; + }); + + spyOn(firebase.auth.EmailAuthProvider, 'credential').and.returnValue(fakePromise()); + + authService.$linkUser(email, password); + expect(firebase.auth.EmailAuthProvider.credential).toHaveBeenCalledWith(email, password); + }); + + it('should call Firebase User\'s link method with email credentials', function () { + var email = 'somebody@somewhere.com', + password = 'myPass', + mockCredentials = 'mock credentials'; + var fbUser = { + provider: 'password', + uid: 'testUid', + link: jasmine.createSpy() + }; + spyOn(authService._, 'getAuth').and.callFake(function () { + return fbUser; + }); + + spyOn(firebase.auth.EmailAuthProvider, 'credential').and.returnValue(mockCredentials); + + authService.$linkUser(email, password); + + expect(fbUser.link).toHaveBeenCalledWith(mockCredentials); + }); + + it('should resolve promise with the user', function (done) { + var email = 'somebody@somewhere.com', + password = 'myPass', + mockCredentials = 'mock credentials'; + var mockUser = { + provider: 'password', + uid: 'testUid', + link: jasmine.createSpy().and.callFake(function (aCredential) { + if (aCredential === mockCredentials) { + return Promise.resolve(mockUser); + } + return Promise.reject(new Error('Wrong mail / password')); + }) + }; + spyOn(authService._, 'getAuth').and.callFake(function () { + return mockUser; + }); + + spyOn(firebase.auth.EmailAuthProvider, 'credential').and.returnValue(mockCredentials); + + authService.$linkUser(email, password) + .then(function (aUser) { + expect(aUser).toBe(mockUser); + done(); + }) + .catch(function (err) { + fail('failed due to an error in promise chain: ' + err.message); + }); + }); + + it('should throw an error if there\'s no current user', function () { + spyOn(authService._, 'getAuth').and.returnValue(null); + + expect(function () { authService.$linkUser('noone@nowhere.com', 'nevermind'); }).toThrow(new Error('No user to link to (user must login before linking)')); + }); + }); });