Created
August 22, 2019 13:17
-
-
Save razbakov/44bd955a80ce72a15d51efa903316248 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
import * as Sentry from '@sentry/browser' | |
import axios from 'axios' | |
import _ from 'lodash' | |
import { Platform, Notify } from 'quasar' | |
import Firebase from 'firebase/app' | |
import 'firebase/auth' | |
import 'firebase/messaging' | |
import moment from 'moment' | |
export default { | |
namespaced: true, | |
state: { | |
language: '', | |
uid: null, | |
user: null, | |
token: '', | |
loginPopup: false, | |
returnUrl: '', | |
profile: null, | |
account: null, | |
searchLocation: {}, | |
pendingAccount: null, | |
next: undefined | |
}, | |
mutations: { | |
nextAction (state, payload) { | |
state.next = payload | |
}, | |
pendingAccount (state, payload) { | |
state.pendingAccount = payload | |
}, | |
setAccount (state, payload) { | |
state.account = payload | |
}, | |
setProfile (state, payload) { | |
state.profile = payload | |
}, | |
setLanguage (state, payload) { | |
state.language = payload | |
}, | |
setUser (state, payload) { | |
state.user = payload | |
if (payload) { | |
state.uid = payload.uid | |
} else { | |
state.uid = null | |
} | |
}, | |
setToken (state, payload) { | |
state.token = payload | |
} | |
}, | |
actions: { | |
setLanguage ({ dispatch, commit, state }, payload) { | |
if (state.uid) { | |
dispatch('updateAccount', { language: payload }) | |
} | |
commit('setLanguage', payload) | |
}, | |
register ({ state }, payload) { | |
Vue.gtm.trackEvent({ | |
category: 'Popup', | |
action: 'Register', | |
label: payload | |
}) | |
state.loginPopup = 'register' | |
}, | |
forgotPassword ({ state }, payload) { | |
Vue.gtm.trackEvent({ | |
category: 'Popup', | |
action: 'ForgotPassword', | |
label: payload | |
}) | |
state.loginPopup = 'password' | |
}, | |
login ({ state }, payload) { | |
Vue.gtm.trackEvent({ | |
category: 'Popup', | |
action: 'Login', | |
label: payload | |
}) | |
state.loginPopup = 'login' | |
}, | |
async changeSearchLocation ({ state, dispatch, rootState }, payload) { | |
if (!payload) { | |
state.searchLocation = null | |
return | |
} | |
if (!payload.name) { | |
return | |
} | |
state.searchLocation = payload | |
if (state.uid) { | |
dispatch('updateAccount', { searchLocation: payload }) | |
} | |
if (!payload.saved) { | |
const city = await rootState.$db | |
.collection('cities') | |
.doc(payload.name) | |
.get() | |
if (!city.exists) { | |
payload.createdBy = state.uid | |
payload.createdAt = new Date() | |
rootState.$db | |
.collection('cities') | |
.doc(payload.name) | |
.set(payload) | |
} | |
} | |
}, | |
hideLogin ({ state }) { | |
state.loginPopup = 'off' | |
state.returnUrl = '' | |
}, | |
async signUserUp ({ commit }, payload) { | |
commit('setLoggingIn', true, { root: true }) | |
commit('clearError', null, { root: true }) | |
commit('pendingAccount', { | |
firstName: payload.firstName, | |
lastName: payload.lastName, | |
gender: payload.gender, | |
phone: payload.phone, | |
email: payload.email | |
}) | |
try { | |
await Firebase | |
.auth() | |
.createUserWithEmailAndPassword(payload.email, payload.password) | |
} catch (error) { | |
commit('setLoggingIn', false, { root: true }) | |
commit('setError', error, { root: true }) | |
} | |
}, | |
async sendPasswordResetEmail ({ commit }, email) { | |
commit('setLoggingIn', true, { root: true }) | |
try { | |
await Firebase.auth().sendPasswordResetEmail(email) | |
commit('setLoggingIn', false, { root: true }) | |
} catch (error) { | |
commit('setLoggingIn', false, { root: true }) | |
commit('setError', error, { root: true }) | |
} | |
}, | |
async signUserIn ({ commit }, payload) { | |
commit('clearError', null, { root: true }) | |
commit('setLoggingIn', true, { root: true }) | |
try { | |
await Firebase | |
.auth() | |
.signInWithEmailAndPassword(payload.email, payload.password) | |
} catch (error) { | |
commit('setLoggingIn', false, { root: true }) | |
commit('setError', error, { root: true }) | |
} | |
}, | |
signUserInTwiiter ({ commit }) { | |
commit('clearError', null, { root: true }) | |
commit('setLoggingIn', true, { root: true }) | |
const provider = new Firebase.auth.TwitterAuthProvider() | |
Firebase.auth().signInWithRedirect(provider) | |
}, | |
signUserInGoogle ({ commit }) { | |
commit('clearError', null, { root: true }) | |
commit('setLoggingIn', true, { root: true }) | |
const provider = new Firebase.auth.GoogleAuthProvider() | |
provider.addScope('https://www.googleapis.com/auth/userinfo.email') | |
Firebase.auth().signInWithRedirect(provider) | |
}, | |
async getRedirectResult ({ dispatch, commit }) { | |
try { | |
const result = await Firebase.auth().getRedirectResult() | |
dispatch('loadUser', result.user) | |
} catch (error) { | |
commit('setError', error, { root: true }) | |
} | |
}, | |
signUserInFacebook ({ commit }) { | |
commit('clearError', null, { root: true }) | |
commit('setLoggingIn', true, { root: true }) | |
const provider = new Firebase.auth.FacebookAuthProvider() | |
provider.addScope('email') | |
Firebase.auth().signInWithRedirect(provider) | |
}, | |
async signInWithEmailLink ({ commit }, payload) { | |
const email = payload.email | |
if (!email || email.length < 3) { | |
return | |
} | |
commit('clearError', null, { root: true }) | |
let result | |
try { | |
result = await Firebase | |
.auth() | |
.signInWithEmailLink(email, payload.link) | |
} catch (error) { | |
commit('setError', error, { root: true }) | |
} | |
console.log('signInWithEmailLink', result, payload) | |
// commit('setReturnUrl', payload.returnUrl, { root: true }) | |
// commit('setReferrer', payload.referrer, { root: true }) | |
}, | |
async sendSignInLinkToEmail ({ commit, rootState }, payload) { | |
commit('clearError', null, { root: true }) | |
let url = `${window.location.origin}/user/signin` | |
let utm = {} | |
let referrer = '' | |
let clientId = '' | |
if (rootState.shared.utm) { | |
utm = rootState.shared.utm | |
} | |
if (rootState.shared.referrer) { | |
referrer = rootState.shared.referrer | |
} | |
if (rootState.shared.clientId) { | |
clientId = rootState.shared.clientId | |
} | |
const params = { | |
email: payload.email, | |
clientId, | |
returnUrl: payload.returnUrl, | |
referrer, | |
...utm | |
} | |
url += '?' + Object.entries(params).map(([key, val]) => `${key}=${val}`).join('&') | |
try { | |
await Firebase | |
.auth() | |
.sendSignInLinkToEmail(payload.email, { | |
url, | |
handleCodeInApp: true | |
}) | |
} catch (error) { | |
commit('setError', error, { root: true }) | |
throw error | |
} | |
}, | |
async logout ({ state, commit }) { | |
if (window && window.dataLayer && state.id) { | |
window.dataLayer.push({ | |
event: 'logout', | |
target: 'logout' | |
}) | |
} | |
commit('setAccount', null) | |
commit('setProfile', null) | |
commit('setUser', null) | |
await Firebase.auth().signOut() | |
}, | |
async updateProfile ({ state, rootState, dispatch }, payload) { | |
await rootState.$db | |
.collection('profiles') | |
.doc(state.uid) | |
.update(payload) | |
await dispatch('loadProfile') | |
}, | |
async updateAccount ({ state, rootState, dispatch, commit }, account) { | |
try { | |
if (state.account && account && state.account.email !== account.email) { | |
await dispatch('updateEmail', account.email) | |
} | |
if (account.password) { | |
const user = Firebase.auth().currentUser | |
await user.updatePassword(account.password) | |
} | |
account = _.omit(account, 'password') | |
await rootState.$db | |
.collection('users') | |
.doc(state.uid) | |
.update(account) | |
await dispatch('loadAccount') | |
} catch (error) { | |
commit('setError', error, { root: true }) | |
await dispatch('loadAccount') | |
throw error | |
} | |
}, | |
async loadAccount ({ rootState, state, commit, dispatch }) { | |
const doc = await rootState.$db.collection('users').doc(state.uid).get() | |
const account = doc.data() | |
account.activated = Boolean(account.email && account.phone && account.gender && account.firstName && account.lastName) | |
commit('setAccount', account) | |
await dispatch('loadProfile') | |
}, | |
sendNotification ({ state }, notification) { | |
if (!notification.to.token) { | |
return | |
} | |
axios({ | |
url: 'https://fcm.googleapis.com/fcm/send', | |
method: 'post', | |
headers: { | |
Authorization: `key=${process.env.VUE_APP_GOOGLE_SERVER_KEY}` | |
}, | |
data: { | |
notification: { | |
title: notification.title, | |
body: notification.message, | |
icon: state.profile.avatar, | |
click_action: `${process.env.VUE_APP_BASE_URI}/chat/${state.uid}` | |
}, | |
to: notification.to.token | |
} | |
}) | |
}, | |
initMessages ({ dispatch, rootState }) { | |
if (Firebase.messaging.isSupported()) { | |
Firebase.messaging().usePublicVapidKey( | |
process.env.VUE_APP_GOOGLE_MESSAGING_KEY | |
) | |
Firebase.messaging().onMessage(function (payload) { | |
Notify.create({ | |
type: 'info', | |
message: payload.notification.title, | |
detail: payload.notification.body, | |
avatar: payload.notification.icon, | |
actions: [ | |
{ | |
label: 'Reply', | |
icon: 'chat', | |
noDismiss: true, | |
handler: payload.notification.click_action | |
} | |
] | |
}) | |
}) | |
} | |
if (!Firebase.messaging.isSupported()) { | |
dispatch('updateAccount', { notifications: false, token: null }) | |
return | |
} | |
const messaging = Firebase.messaging() | |
messaging | |
.requestPermission() | |
.then(function () { | |
dispatch('updateAccount', { notifications: true }) | |
}) | |
.catch(function () { | |
dispatch('updateAccount', { notifications: false }) | |
}) | |
rootState.shared.notificationsAreRequested = true | |
messaging | |
.getToken() | |
.then(function (currentToken) { | |
if (currentToken) { | |
dispatch('updateAccount', { token: currentToken }) | |
} else { | |
console.log( | |
'No Instance ID token available. Request permission to generate one.' | |
) | |
} | |
}) | |
.catch(function (err) { | |
if (err.code === 'messaging/notifications-blocked') { | |
rootState.shared.notificationsAreBlocked = true | |
} else { | |
console.log('An error occurred while retrieving token. ', err) | |
} | |
}) | |
messaging.onTokenRefresh(function () { | |
messaging | |
.getToken() | |
.then(function (refreshedToken) { | |
dispatch('updateAccount', { token: refreshedToken }) | |
}) | |
.catch(function (err) { | |
console.log('Unable to retrieve refreshed token ', err) | |
}) | |
}) | |
}, | |
async sendEmailVerification ({ commit }) { | |
try { | |
const user = Firebase.auth().currentUser | |
await user.sendEmailVerification() | |
} catch (error) { | |
commit('setError', error, { root: true }) | |
throw error | |
} | |
}, | |
async updateEmail ({ commit }, email) { | |
if (!email) { | |
return | |
} | |
try { | |
const user = Firebase.auth().currentUser | |
await user.updateEmail(email) | |
await user.sendEmailVerification() | |
} catch (error) { | |
commit('setError', error, { root: true }) | |
throw error | |
} | |
}, | |
async loadProfile ({ state, commit, rootState }) { | |
const docRef = rootState.$db.collection('profiles').doc(state.uid) | |
let doc | |
doc = await docRef.get() | |
if (!doc.exists) { | |
const account = state.account | |
if (!state.account) { | |
commit('setProfile', null) | |
return | |
} | |
await docRef.set({ | |
id: state.uid, | |
name: account.name || '', | |
gender: account.gender || null, | |
cover: account.cover || '', | |
avatar: account.avatar || '', | |
moto: account.moto || '', | |
gallery: account.gallery || {} | |
}) | |
doc = await docRef.get() | |
} | |
commit('setProfile', doc.data()) | |
}, | |
async loadUser ({ commit, dispatch, rootState, state }, user) { | |
if (!user || !user.uid) { | |
return | |
} | |
dispatch('hideLogin') | |
const providerData = user.providerData ? user.providerData[0] : { | |
email: user.email, | |
displayName: user.displayName, | |
providerId: 'email-password' | |
} | |
const userDocRef = rootState.$db.collection('users').doc(user.uid) | |
Sentry.configureScope(scope => { | |
scope.setUser({ | |
email: providerData.email, | |
id: user.uid, | |
name: providerData.displayName | |
}) | |
}) | |
const doc = await userDocRef.get() | |
let account = {} | |
if (doc.exists) { | |
account = doc.data() | |
commit('setLanguage', account.language) | |
if (!state.uid) { | |
Vue.gtm.trackEvent({ | |
category: 'User', | |
action: 'Login', | |
label: providerData ? providerData.providerId : 'unknown' | |
}) | |
} | |
} else { | |
account = { ...state.pendingAccount } | |
if (account && account.email) { | |
await dispatch('updateEmail', account.email) | |
} | |
Vue.gtm.trackEvent({ | |
category: 'User', | |
action: 'SignUp', | |
label: providerData ? providerData.providerId : 'unknown' | |
}) | |
} | |
commit('pendingAccount', null) | |
account.version = rootState.shared.version | |
account.emailVerified = user.emailVerified | |
if (account.firstName && account.lastName) { | |
account.name = `${account.firstName} ${account.lastName}` | |
} else { | |
if (!account.name && providerData.displayName) { | |
account.name = providerData.displayName | |
} | |
if (account.name) { | |
let [firstName, lastName] = [...account.name.split(' ')] | |
account.firstName = firstName || '' | |
account.lastName = lastName || '' | |
} | |
} | |
if (!account.email && providerData) { | |
account.email = providerData.email | |
} | |
if (!account.registeredAt) { | |
account.registeredAt = Date.now() | |
} | |
if (!account.daysUsed) { | |
account.daysUsed = 1 | |
} | |
if (account.lastLoginAt) { | |
const isSameDay = moment(account.lastLoginAt).isSame(moment(), 'day') | |
if (!isSameDay) { | |
account.daysUsed = account.daysUsed + 1 | |
} | |
} | |
account.lastLoginAt = Date.now() | |
if ((!account.avatar || !account.avatar.includes('firebasestorage')) && providerData.photoURL && providerData.photoURL.includes('facebook')) { | |
account.avatar = providerData.photoURL + '?height=500' | |
} | |
if (!account.provider) { | |
account.provider = providerData.providerId | |
} | |
if (!account.providerUid) { | |
account.providerUid = providerData.uid | |
} | |
account.pwa = window && window.matchMedia('(display-mode: standalone)').matches | |
account.pwaUsed = account.pwaUsed || account.pwa | |
account.extra = { | |
clientId: rootState.shared.clientId, | |
utm: rootState.shared.utm, | |
referrer: rootState.shared.referrer, | |
promo: rootState.shared.promo, | |
ref: rootState.shared.ref, | |
userLanguage: window ? window.navigator.userLanguage || '' : '', | |
systemLanguage: window ? window.navigator.systemLanguage || '' : '', | |
browserLanguage: window ? window.navigator.browserLanguage || '' : '', | |
language: window ? window.navigator.language || '' : '', | |
languages: window ? window.navigator.languages || '' : '', | |
geo: rootState.shared.geo || '', | |
location: rootState.shared.location || '', | |
platform: Platform.is, | |
userAgent: window ? navigator.userAgent || navigator.vendor || window.opera : '' | |
} | |
if (!account.initialExtra) { | |
account.initialExtra = account.extra | |
} | |
await rootState.$db | |
.collection('users') | |
.doc(user.uid) | |
.set(account) | |
commit('setUser', user) | |
Sentry.configureScope(scope => { | |
scope.setUser({ | |
email: account.email, | |
id: user.uid, | |
username: account.name, | |
name: account.name | |
}) | |
}) | |
await dispatch('loadAccount') | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment