diff --git a/packages/firebase-auth-module/.browserslistrc b/packages/firebase-auth-module/.browserslistrc new file mode 100644 index 00000000..bd3ad98e --- /dev/null +++ b/packages/firebase-auth-module/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not ie <= 8 \ No newline at end of file diff --git a/packages/firebase-auth-module/README.md b/packages/firebase-auth-module/README.md new file mode 100644 index 00000000..ae16357a --- /dev/null +++ b/packages/firebase-auth-module/README.md @@ -0,0 +1,37 @@ +# vuex-firebase-auth-module + +Vuex module to interface with Google Firebase + +Docs Link: Coming Soon! + +Install: +```bash +yarn add @vuetify/vuex-firebase-auth-module +``` + +Import into your project's entry point (main.js in most Vue projects) +```js +import attachFirebaseAuthModule from '@vuetify/vuex-firebase-auth-module'; +``` + +Attach auth module to the store +```js +import firebase from 'firebase/app' +import 'firebase/auth' + +import store from './store'; + +const config = { + apiKey: 'your-api-key', + authDomain: 'your-auth-domain', + databaseURL: 'your-database-url', + projectId: 'your-project-id', + storageBucket: 'your-storage-bucket', + messagingSenderId: 'your-sender-id', +} + +const firebaseApp = firebase.initializeApp(config) +const auth = firebaseApp.auth() + +attachFirebaseAuthModule(store, auth, 'auth') +``` diff --git a/packages/firebase-auth-module/docs.now.json b/packages/firebase-auth-module/docs.now.json new file mode 100644 index 00000000..03d90e13 --- /dev/null +++ b/packages/firebase-auth-module/docs.now.json @@ -0,0 +1,11 @@ +{ + "name": "vuetify-vuex-firebase-auth-module-docs", + "type": "static", + "static": { + "public": "docs/.vuepress/dist" + }, + "alias": "firebase-auth.vuetifyjs.com", + "files": [ + "docs/.vuepress/dist" + ] +} diff --git a/packages/firebase-auth-module/docs/.vuepress/config.js b/packages/firebase-auth-module/docs/.vuepress/config.js new file mode 100755 index 00000000..7b035a48 --- /dev/null +++ b/packages/firebase-auth-module/docs/.vuepress/config.js @@ -0,0 +1,46 @@ +module.exports = { + title: 'Vuetify Vuex ', + + head: [ + ['link', { rel: 'icon', href: `/logo.png` }] + ], + + // ga: 'UA-75262397-5', // TODO: add me + + themeConfig: { + nav: [ + { + text: 'Get Help', + link: 'https://discord.gg/q6UtSjz' + }, + { + text: 'Firebase Auth Dev Resources', + link: 'https://firebase.google.com/docs/reference/js/firebase.auth/' + } + ], + sidebar: [ + { + title: 'Getting started', + collapsable: false, + children: [ + 'guide/install' + ] + }, + { + title: 'API', + collapsable: false, + children: [ + 'api/actions', + 'api/getters' + ] + }, + { + title: 'Firebase Auth', + collapsable: false, + children: [ + 'firebase/setup', + ] + } + ] + } +} diff --git a/packages/firebase-auth-module/docs/.vuepress/public/add-project.png b/packages/firebase-auth-module/docs/.vuepress/public/add-project.png new file mode 100644 index 00000000..b6bab828 Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/add-project.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/console-auth.png b/packages/firebase-auth-module/docs/.vuepress/public/console-auth.png new file mode 100644 index 00000000..ccc5069d Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/console-auth.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/copy-config.png b/packages/firebase-auth-module/docs/.vuepress/public/copy-config.png new file mode 100644 index 00000000..d0a69fd6 Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/copy-config.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/enable-email-pass.png b/packages/firebase-auth-module/docs/.vuepress/public/enable-email-pass.png new file mode 100644 index 00000000..df201b6b Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/enable-email-pass.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/get-setup-config.png b/packages/firebase-auth-module/docs/.vuepress/public/get-setup-config.png new file mode 100644 index 00000000..e208decd Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/get-setup-config.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/getting-started.png b/packages/firebase-auth-module/docs/.vuepress/public/getting-started.png new file mode 100644 index 00000000..e2fff4cf Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/getting-started.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/logo.png b/packages/firebase-auth-module/docs/.vuepress/public/logo.png new file mode 100644 index 00000000..34ae50fd Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/logo.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/project-ready.png b/packages/firebase-auth-module/docs/.vuepress/public/project-ready.png new file mode 100644 index 00000000..bc90cc78 Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/project-ready.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/project-setup.png b/packages/firebase-auth-module/docs/.vuepress/public/project-setup.png new file mode 100644 index 00000000..0a98d4fa Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/project-setup.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/select-methods.png b/packages/firebase-auth-module/docs/.vuepress/public/select-methods.png new file mode 100644 index 00000000..92aad774 Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/select-methods.png differ diff --git a/packages/firebase-auth-module/docs/.vuepress/public/setup-methods.png b/packages/firebase-auth-module/docs/.vuepress/public/setup-methods.png new file mode 100644 index 00000000..5ae64b2e Binary files /dev/null and b/packages/firebase-auth-module/docs/.vuepress/public/setup-methods.png differ diff --git a/packages/firebase-auth-module/docs/README.md b/packages/firebase-auth-module/docs/README.md new file mode 100644 index 00000000..a5d44b5a --- /dev/null +++ b/packages/firebase-auth-module/docs/README.md @@ -0,0 +1,8 @@ +--- +home: true +heroImage: /logo.png +actionText: Get Started → +actionLink: /guide/install +tagline: 'Firebase Auth Module' +footer: MIT Licensed | Copyright © 2018-present Vuetify LLC +--- diff --git a/packages/firebase-auth-module/docs/api/actions.md b/packages/firebase-auth-module/docs/api/actions.md new file mode 100644 index 00000000..88fbcca0 --- /dev/null +++ b/packages/firebase-auth-module/docs/api/actions.md @@ -0,0 +1,296 @@ +# Actions + +## Actions on the Firebase User object +See Firebase User Reference for more details: [Firebase User Reference](https://firebase.google.com/docs/reference/js/firebase.User) + +### resendVerification + +Sends email verification to logged in user. +Calls `sendEmailVerification` on `auth.currentUser`. + +##### returns +Void + +
+ +### reloadUser + +Reloads the firebase user object, and refreshes any values updated externally since last load. (e.g. user verified email) + +##### returns +Void + +
+ +### updateProfile + +##### params +`{ photoURL: string, displayName: string }` + +Updates users profile information, namely displayName and photoURL. + +##### returns +Void + + +
+ +### getIdToken + +##### returns + + +
+ +### getIdTokenResult + +##### returns + + +
+ +### toJSON +Serializes the current user +##### returns +JSON of the current user + +
+ +### updateEmail + +##### returns + + +
+ +### updatePassword + +##### returns + + +
+ +### updatePhoneNumber + +##### returns + + + + +## Actions on the Firebase Auth object +See Firebase Reference for more details: [Firebase Reference](https://firebase.google.com/docs/reference/js/firebase.auth.Auth) + +
+ +### applyActionCode +Applies a verification code sent to the user by email or other out-of-band mechanism. + +##### params +code e.g. `12345` + +##### returns +Empty Promise + +
+ +### checkActionCode +Checks a verification code sent to the user by email or other out-of-band mechanism. + +##### params +code e.g. `12345` + + +##### returns +Returns metadata about the code. +
+ +### confirmPasswordReset + +Resets user's password given a code sent from [sendPasswordResetEmail](/api/actions.html#sendpasswordresetemail) + +##### params +`{ code: string, newPassword: string }` + +##### returns +Void + + +
+ +### createUserWithEmailAndPassword + +Registers a user with custom email and password. + +##### params +`{email: string, password: string}` + +##### returns +Firebase Auth.User Object + +
+ +### fetchSignInMethodsForEmail +See: [Firebase Docs](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#fetchsigninmethodsforemail) +
+Gets the list of possible sign in methods for the given email address. This is useful to differentiate methods of sign-in for the same provider, eg. `EmailAuthProvider` which has 2 methods of sign-in, email/password and email/link. + +##### returns + +
+ +### getRedirectResult +Returns a UserCredential from the redirect-based sign-in flow. +##### returns +[UserCredential](https://firebase.google.com/docs/reference/js/firebase.auth.html#usercredential) +
+ +### isSignInWithEmailLink +Checks if an incoming link is a sign-in with email link. + +##### params +`emailLink`: string + +##### returns +Boolean +
+ +### sendPasswordResetEmail + +Sends user an email containing a code to reset their password. + +##### params +`"email@email.com"` + +##### returns +Void + +
+ +### sendSignInLinkToEmail + +##### returns + +
+ +### setPersistence +Changes the current type of persistence on the current Auth instance for the currently saved Auth session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. This will return a promise that will resolve once the state finishes copying from one type of storage to the other. Calling a sign-in method after changing persistence will wait for that persistence change to complete before applying it on the new Auth state. + +This makes it easy for a user signing in to specify whether their session should be remembered or not. It also makes it easier to never persist the Auth state for applications that are shared by other users or have sensitive data. + +##### params +`local` or `session` or `none` +
+**Default**: `local` + +##### returns +null + +
+ +### signInAndRetrieveDataWithCredential + +##### returns + +
+ +### signInAndRetrieveDataWithCustomToken + +##### returns + +
+ +### signInAndRetrieveDataWithEmailAndPassword + +##### returns + +
+ +### signInAnonymously + +##### returns + +
+ +### signInAnonymouslyAndRetrieveData + +##### returns + +
+ +### signInWithCredential + +##### returns + +
+ +### signInWithCustomToken + +##### returns + +
+ +### signInWithEmailAndPassword + +Logs in a user with email and password sign in method + +#### params +`{ email: string, password: string}` + +##### returns +[Firebase Auth User Credential](https://firebase.google.com/docs/reference/js/firebase.auth#.UserCredential) + +
+ +### signInWithEmailLink + +##### returns + +
+ +### signInWithPhoneNumber + +##### returns + +
+ +### signInWithPopup + +##### returns + +
+ +### signInWithRedirect + +##### returns + +
+ +### signOut + +Logs out the user + +##### returns +Void + +
+ +### updateCurrentUser + +##### returns + +
+ +### useDeviceLanguage +Sets the current language to the default device/browser preference. +##### returns +null +
+ +### verifyPasswordResetCode +Checks a password reset code sent to the user by email or other out-of-band mechanism. + +##### params +`"code"`:string + +##### returns +"user's email": string if valid, \ No newline at end of file diff --git a/packages/firebase-auth-module/docs/api/getters.md b/packages/firebase-auth-module/docs/api/getters.md new file mode 100644 index 00000000..8e811414 --- /dev/null +++ b/packages/firebase-auth-module/docs/api/getters.md @@ -0,0 +1,5 @@ +# Getters + +`isLoggedIn`: Boolean indicating logged in state + +`isVerified`: Boolean indicating if the user has verified their email diff --git a/packages/firebase-auth-module/docs/firebase/setup.md b/packages/firebase-auth-module/docs/firebase/setup.md new file mode 100644 index 00000000..76fb336e --- /dev/null +++ b/packages/firebase-auth-module/docs/firebase/setup.md @@ -0,0 +1,45 @@ +# Configuring Firebase Auth + +## Setup Firebase Project + +If you've already created a firebase project, skip to step 5. + +1. Navigate to [Firebase](https://firebase.google.com) ![Firebase Welcome Screen](/getting-started.png) + +2. Create new project ![Firebase Welcome Screen](/add-project.png) + +3. Setup new project ![Project Setup](/project-setup.png) + +4. After setup is completed, click "continue" ![Project Ready](/project-ready.png) + +5. In the Firebase console, click "Authentication" ![Firebase Console](/console-auth.png) + +6. On Firebase Auth screen, Setup new sign in methods ![Setup Sign In Methods](/setup-methods.png) + +7. Select Email/Password ![Email Methods](/select-methods.png) + +8. Enable it and save ![Enable Email](/enable-email-pass.png) + +9. Let's now get the config to add to your project, Click "Web Setup" ![Setup](/get-setup-config.png) + +10. Copy whats in the red box ![Web Setup Config](/copy-config.png) + +11. Add it to main.js + +```js +import firebase from 'firebase/app' +import 'firebase/auth' + +const config = { + apiKey: 'your-api-key', + authDomain: 'your-auth-domain', + databaseURL: 'your-database-url', + projectId: 'your-project-id', + storageBucket: 'your-storage-bucket', + messagingSenderId: 'your-sender-id', +} + +const firebaseApp = firebase.initializeApp(config) +const auth = firebaseApp.auth() + +``` \ No newline at end of file diff --git a/packages/firebase-auth-module/docs/guide/install.md b/packages/firebase-auth-module/docs/guide/install.md new file mode 100755 index 00000000..9eb019a7 --- /dev/null +++ b/packages/firebase-auth-module/docs/guide/install.md @@ -0,0 +1,50 @@ +# Install + +Vuex module to interface with Google Firebase Auth + +Install: +```bash +yarn add firebase +yarn add @vuetify/vuex-firebase-auth-module +``` + +Import into your project's entry point (**src/main.js** in most Vue projects) + +```js +import attachFirebaseAuthModule from '@vuetify/vuex-firebase-auth-module' +``` + +Attach firebase auth module to the store +```js +// config from firebase setup +import firebase from 'firebase/app' +import 'firebase/auth' +``` + +```js +// import your store +import store from './store' +``` + +```js +// config from firebase setup +const config = { + apiKey: 'your-api-key', + authDomain: 'your-auth-domain', + databaseURL: 'your-database-url', + projectId: 'your-project-id', + storageBucket: 'your-storage-bucket', + messagingSenderId: 'your-sender-id', +} + +const firebaseApp = firebase.initializeApp(config) +const auth = firebaseApp.auth() +``` + +```js +// attach the module to your store +attachFirebaseAuthModule(store, auth, 'auth') +``` + +### Example Project +An example project can be found [here](https://github.com/vuetifyjs/vuex-firebase-auth-example) diff --git a/packages/firebase-auth-module/package.json b/packages/firebase-auth-module/package.json new file mode 100644 index 00000000..44c2b220 --- /dev/null +++ b/packages/firebase-auth-module/package.json @@ -0,0 +1,35 @@ +{ + "name": "@vuetify/vuex-firebase-auth-module", + "version": "0.4.0", + "main": "dist/vuex-firebase-auth-module.umd.min.js", + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build --target lib --name vuex-firebase-auth-module src/index.js", + "lint": "vue-cli-service lint", + "docs:deploy": "npm run docs:build && now --local-config docs.now.json && now alias --local-config docs.now.json", + "docs:dev": "vuepress dev docs", + "docs:build": "vuepress build docs" + }, + "dependencies": { + "firebase": "^5.6.0" + }, + "devDependencies": { + "@vue/babel-preset-app": "^3.0.4", + "@vue/cli-plugin-babel": "^3.0.4", + "@vue/cli-plugin-eslint": "^3.0.4", + "@vue/cli-service": "^3.0.4", + "@vue/eslint-config-standard": "^3.0.4", + "lint-staged": "^7.2.0", + "vue-template-compiler": "^2.5.17", + "vuepress": "^0.14.2" + }, + "gitHooks": { + "pre-commit": "lint-staged" + }, + "lint-staged": { + "*.js": [ + "vue-cli-service lint", + "git add" + ] + } +} diff --git a/packages/firebase-auth-module/public/favicon.ico b/packages/firebase-auth-module/public/favicon.ico new file mode 100644 index 00000000..c7b9a43c Binary files /dev/null and b/packages/firebase-auth-module/public/favicon.ico differ diff --git a/packages/firebase-auth-module/public/index.html b/packages/firebase-auth-module/public/index.html new file mode 100644 index 00000000..29492839 --- /dev/null +++ b/packages/firebase-auth-module/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + vuex-firebase-auth-module-new + + + +
+ + + diff --git a/packages/firebase-auth-module/src/actions.js b/packages/firebase-auth-module/src/actions.js new file mode 100644 index 00000000..6746feb9 --- /dev/null +++ b/packages/firebase-auth-module/src/actions.js @@ -0,0 +1,160 @@ +let auth // auth object created from firebase.auth() + +const notImplemented = () => { console.warn('Not implemented yet') } + +export default { + init ({ dispatch }, config) { + auth = config + auth.onAuthStateChanged(user => dispatch('authStateChanged', user)) + // TODO: auth.onIdTokenChanged + }, + /// Auth methods + authStateChanged: ({ commit, state }, user) => { + if (!state.init) commit('setInit') + commit('setUser', user) + }, + applyActionCode: (_, code) => + new Promise((resolve, reject) => { + auth.applyActionCode(code) + .then(resolve) + .catch(reject) + }), + checkActionCode: (_, code) => + new Promise((resolve, reject) => { + auth.checkActionCode(code) + .then(resolve) + .catch(reject) + }), + confirmPasswordReset: (_, payload) => + new Promise((resolve, reject) => { + auth.confirmPasswordReset(payload.code, payload.newPassword) + .then(resolve) + .catch(reject) + }), + createUserWithEmailAndPassword: ({ commit }, payload) => + new Promise((resolve, reject) => { + auth.createUserWithEmailAndPassword(payload.email, payload.password) + .then(() => { + const user = auth.currentUser + user.sendEmailVerification() + commit('setUser', user) + resolve(user) + }) + .catch(reject) + }), + fetchSignInMethodsForEmail: (_, email) => + new Promise((resolve, reject) => { + auth.fetchSignInMethodsForEmail(email) + .then(resolve) + .catch(reject) + }), + getRedirectResult: () => + new Promise((resolve, reject) => { + auth.getRedirectResult() + .then(resolve) + .catch(reject) + }), + isSignInWithEmailLink: (_, emailLink) => + new Promise((resolve, reject) => { + auth.isSignInWithEmailLink(emailLink) + .then(resolve) + .catch(reject) + }), + sendPasswordResetEmail: (_, email) => + new Promise((resolve, reject) => { + auth.sendPasswordResetEmail(email) + .then(resolve) + .catch(reject) + }), + sendSignInLinkToEmail: notImplemented, + setPersistence: (_, type) => { + if (!['session', 'local', 'none'].includes(type)) { + throw new Error('`type` must be one of `session`, `local`, `none`') + } + auth.setPersistence(type.toLowerCase()) + }, + signInAndRetrieveDataWithCredential: notImplemented, + signInAndRetrieveDataWithCustomToken: notImplemented, + signInAndRetrieveDataWithEmailAndPassword: notImplemented, + signInAnonymously: notImplemented, + signInAnonymouslyAndRetrieveData: notImplemented, + signInWithCredential: notImplemented, + signInWithCustomToken: notImplemented, + signInWithEmailAndPassword: ({ commit }, credentials) => + new Promise((resolve, reject) => { + auth.signInWithEmailAndPassword(credentials.email, credentials.password) + .then(resolve) + .catch(reject) + }), + signInWithEmailLink: notImplemented, + signInWithPhoneNumber: notImplemented, + signInWithPopup: notImplemented, + signInWithRedirect: notImplemented, + signOut: ({ commit }) => + new Promise((resolve, reject) => { + auth.signOut() + .then(res => { + commit('setUser', {}) + resolve(res) + }) + .catch(reject) + }), + updateCurrentUser: notImplemented, + useDeviceLanguage: () => { + auth.useDeviceLanguage() + }, + verifyPasswordResetCode: (_, code) => + new Promise((resolve, reject) => { + auth.verifyPasswordResetCode(code) + .then(resolve) + .catch(reject) + }), + + /// User Methods + getIdToken: notImplemented, + getIdTokenResult: notImplemented, + toJSON: () => { + const currentUser = auth.currentUser + return currentUser.toJSON() + }, + reauthenticateWithCredential: notImplemented, + reloadUser: ({ commit }) => + new Promise((resolve, reject) => { + const currentUser = auth.currentUser + currentUser.reload() + .then(user => { + commit('setUser', user) + resolve(user) + }) + .catch(reject) + }), + resendVerification: (_, data) => + new Promise((resolve, reject) => { + const currentUser = auth.currentUser + currentUser.sendEmailVerification() + resolve(currentUser) + }), + updateEmail: notImplemented, + updatePassword: notImplemented, + updatePhoneNumber: notImplemented, + updateProfile: ({ commit }, payload) => + new Promise((resolve, reject) => { + const user = auth.currentUser + const profileData = {} + if (payload.photoURL) { + profileData.photoURL = payload.photoURL + } + if (payload.displayName) { + profileData.displayName = payload.displayName + } + if (!Object.keys(profileData).length) { + throw new Error('No data provided.') + } + user.updateProfile(profileData) + .then(res => { + commit('setProfile', profileData) + resolve(res) + }) + .catch(reject) + }) +} diff --git a/packages/firebase-auth-module/src/getters.js b/packages/firebase-auth-module/src/getters.js new file mode 100644 index 00000000..b2ed8816 --- /dev/null +++ b/packages/firebase-auth-module/src/getters.js @@ -0,0 +1,6 @@ +module.exports = { + isLoggedIn: (store = {}) => { + return Boolean(store.user && store.user.uid) + }, + isVerified: (store = {}) => store.user && store.user.emailVerified +} diff --git a/packages/firebase-auth-module/src/index.js b/packages/firebase-auth-module/src/index.js new file mode 100644 index 00000000..58a74036 --- /dev/null +++ b/packages/firebase-auth-module/src/index.js @@ -0,0 +1,19 @@ +import state from './state' +import getters from './getters' +import mutations from './mutations' +import actions from './actions' + +export default (store, authObj, namespace = 'auth', vuexModuleOptions = {}) => { + if (!authObj) { + throw new Error('Auth object required. Did you create it from `firebase.auth()`?') + } + store.registerModule(namespace, { + namespaced: true, + actions, + getters, + mutations, + state + }, vuexModuleOptions) + + store.dispatch(`${namespace}/init`, authObj) +} diff --git a/packages/firebase-auth-module/src/mutations.js b/packages/firebase-auth-module/src/mutations.js new file mode 100644 index 00000000..3708d8ea --- /dev/null +++ b/packages/firebase-auth-module/src/mutations.js @@ -0,0 +1,10 @@ + +export default { + setUser: (state, user) => { + state.user = { ...user } + }, + setProfile: (state, profile) => { + if (profile.photoURL) state.user.photoURL = profile.photoURL + if (profile.displayName) state.user.displayName = profile.displayName + } +} diff --git a/packages/firebase-auth-module/src/state.js b/packages/firebase-auth-module/src/state.js new file mode 100644 index 00000000..0713f681 --- /dev/null +++ b/packages/firebase-auth-module/src/state.js @@ -0,0 +1,7 @@ +const state = () => { + return { + user: {}, + init: false, + } +} +export default state diff --git a/packages/firebase-auth-module/utils/vuex.js b/packages/firebase-auth-module/utils/vuex.js new file mode 100755 index 00000000..47911b88 --- /dev/null +++ b/packages/firebase-auth-module/utils/vuex.js @@ -0,0 +1,2 @@ +// Simple setter +export const set = property => (state, payload) => (state[property] = payload)