+
+
See the list of [contributors](https://github.com/liyasthomas/postwoman/graphs/contributors) who participated in this project.
diff --git a/components/firebase/login.vue b/components/firebase/login.vue
index 06594cb4a..1734db5f3 100644
--- a/components/firebase/login.vue
+++ b/components/firebase/login.vue
@@ -50,64 +50,216 @@ export default {
fb,
}
},
-
methods: {
+ showLoginSuccess() {
+ this.$toast.info(this.$t("login_success"), {
+ icon: "vpn_key",
+ })
+ },
signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider()
+ const self = this
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
- this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
+ self.$toast.info(`${self.$t("turn_on")} ${self.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
- text: this.$t("yes"),
+ text: self.$t("yes"),
onClick: (e, toastObject) => {
- fb.writeSettings("syncHistory", false)
+ fb.writeSettings("syncHistory", true)
fb.writeSettings("syncCollections", true)
- this.$router.push({ path: "/settings" })
+ fb.writeSettings("syncEnvironments", true)
+ self.$router.push({ path: "/settings" })
toastObject.remove()
},
},
})
}
+ self.showLoginSuccess()
})
.catch(err => {
- this.$toast.show(err.message || err, {
- icon: "error",
- })
+ // An error happened.
+ if (err.code === "auth/account-exists-with-different-credential") {
+ // Step 2.
+ // User's email already exists.
+ // The pending Google credential.
+ var pendingCred = err.credential
+ // The provider account's email address.
+ var email = err.email
+ // Get sign-in methods for this email.
+ firebase
+ .auth()
+ .fetchSignInMethodsForEmail(email)
+ .then(function(methods) {
+ // Step 3.
+ // If the user has several sign-in methods,
+ // the first method in the list will be the "recommended" method to use.
+ if (methods[0] === "password") {
+ // Asks the user their password.
+ // In real scenario, you should handle this asynchronously.
+ var password = promptUserForPassword() // TODO: implement promptUserForPassword.
+ auth
+ .signInWithEmailAndPassword(email, password)
+ .then(function(user) {
+ // Step 4a.
+ return user.linkWithCredential(pendingCred)
+ })
+ .then(function() {
+ // Google account successfully linked to the existing Firebase user.
+ self.showLoginSuccess()
+ })
+ return
+ }
+
+ self.$toast.info(`${self.$t("login_with")}`, {
+ icon: "vpn_key",
+ duration: null,
+ closeOnSwipe: false,
+ action: {
+ text: self.$t("yes"),
+ onClick: (e, toastObject) => {
+ // All the other cases are external providers.
+ // Construct provider object for that provider.
+ // TODO: implement getProviderForProviderId.
+ var provider = new firebase.auth.GithubAuthProvider()
+ // At this point, you should let the user know that they already has an account
+ // but with a different provider, and let them validate the fact they want to
+ // sign in with this provider.
+ // Sign in to provider. Note: browsers usually block popup triggered asynchronously,
+ // so in real scenario you should ask the user to click on a "continue" button
+ // that will trigger the signInWithPopup.
+ firebase
+ .auth()
+ .signInWithPopup(provider)
+ .then(function(result) {
+ // Remember that the user may have signed in with an account that has a different email
+ // address than the first one. This can happen as Firebase doesn't control the provider's
+ // sign in flow and the user is free to login using whichever account they own.
+ // Step 4b.
+ // Link to Google credential.
+ // As we have access to the pending credential, we can directly call the link method.
+ result.user
+ .linkAndRetrieveDataWithCredential(pendingCred)
+ .then(function(usercred) {
+ // Google account successfully linked to the existing Firebase user.
+ self.showLoginSuccess()
+ })
+ })
+
+ toastObject.remove()
+ },
+ },
+ })
+ })
+ }
})
},
signInWithGithub() {
const provider = new firebase.auth.GithubAuthProvider()
+ const self = this
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
- this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
+ self.$toast.info(`${self.$t("turn_on")} ${self.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
- text: this.$t("yes"),
+ text: self.$t("yes"),
onClick: (e, toastObject) => {
- fb.writeSettings("syncHistory", false)
+ fb.writeSettings("syncHistory", true)
fb.writeSettings("syncCollections", true)
- this.$router.push({ path: "/settings" })
+ fb.writeSettings("syncEnvironments", true)
+ self.$router.push({ path: "/settings" })
toastObject.remove()
},
},
})
}
+ self.showLoginSuccess()
})
.catch(err => {
- this.$toast.show(err.message || err, {
- icon: "error",
- })
+ // An error happened.
+ if (err.code === "auth/account-exists-with-different-credential") {
+ // Step 2.
+ // User's email already exists.
+ // The pending Google credential.
+ var pendingCred = err.credential
+ // The provider account's email address.
+ var email = err.email
+ // Get sign-in methods for this email.
+ firebase
+ .auth()
+ .fetchSignInMethodsForEmail(email)
+ .then(function(methods) {
+ // Step 3.
+ // If the user has several sign-in methods,
+ // the first method in the list will be the "recommended" method to use.
+ if (methods[0] === "password") {
+ // Asks the user their password.
+ // In real scenario, you should handle this asynchronously.
+ var password = promptUserForPassword() // TODO: implement promptUserForPassword.
+ firebase
+ .auth()
+ .signInWithEmailAndPassword(email, password)
+ .then(function(user) {
+ // Step 4a.
+ return user.linkWithCredential(pendingCred)
+ })
+ .then(function() {
+ // Google account successfully linked to the existing Firebase user.
+ self.showLoginSuccess()
+ })
+ return
+ }
+
+ self.$toast.info(`${self.$t("login_with")}`, {
+ icon: "vpn_key",
+ duration: null,
+ closeOnSwipe: false,
+ action: {
+ text: self.$t("yes"),
+ onClick: (e, toastObject) => {
+ // All the other cases are external providers.
+ // Construct provider object for that provider.
+ // TODO: implement getProviderForProviderId.
+ var provider = new firebase.auth.GoogleAuthProvider()
+ // At this point, you should let the user know that they already has an account
+ // but with a different provider, and let them validate the fact they want to
+ // sign in with this provider.
+ // Sign in to provider. Note: browsers usually block popup triggered asynchronously,
+ // so in real scenario you should ask the user to click on a "continue" button
+ // that will trigger the signInWithPopup.
+ firebase
+ .auth()
+ .signInWithPopup(provider)
+ .then(function(result) {
+ // Remember that the user may have signed in with an account that has a different email
+ // address than the first one. This can happen as Firebase doesn't control the provider's
+ // sign in flow and the user is free to login using whichever account they own.
+ // Step 4b.
+ // Link to Google credential.
+ // As we have access to the pending credential, we can directly call the link method.
+ result.user
+ .linkAndRetrieveDataWithCredential(pendingCred)
+ .then(function(usercred) {
+ self.showLoginSuccess()
+ })
+ })
+
+ toastObject.remove()
+ },
+ },
+ })
+ })
+ }
})
},
},
diff --git a/components/graphql/queryeditor.vue b/components/graphql/queryeditor.vue
index c76ba02d7..6378f5f09 100644
--- a/components/graphql/queryeditor.vue
+++ b/components/graphql/queryeditor.vue
@@ -5,17 +5,17 @@
diff --git a/functions/platformutils.js b/functions/platformutils.js
new file mode 100644
index 000000000..8c285c1d5
--- /dev/null
+++ b/functions/platformutils.js
@@ -0,0 +1,3 @@
+export function getPlatformSpecialKey() {
+ return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl"
+}
diff --git a/lang/en-US.js b/lang/en-US.js
index e7c5e755c..344075d7a 100644
--- a/lang/en-US.js
+++ b/lang/en-US.js
@@ -258,6 +258,7 @@ export default {
installed: "Installed",
login_with: "Login with",
logged_out: "Logged out",
+ login_success: "Successfully logged in",
logout: "Logout",
account: "Account",
scrollInto_use_toggle: "Auto scroll",
diff --git a/layouts/default.vue b/layouts/default.vue
index 6b18381da..a77c8871b 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -642,6 +642,7 @@ import intializePwa from "../assets/js/pwa"
import * as version from "../.postwoman/version.json"
import { hasExtensionInstalled } from "../functions/strategies/ExtensionStrategy"
import { hasChromeExtensionInstalled } from "../functions/strategies/ChromeStrategy"
+import { getPlatformSpecialKey } from "~/functions/platformutils"
import firebase from "firebase/app"
import { fb } from "../functions/fb"
@@ -653,9 +654,7 @@ export default {
},
methods: {
- getSpecialKey() {
- return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl"
- },
+ getSpecialKey: getPlatformSpecialKey,
linkActive(path) {
return {
"nuxt-link-exact-active": this.$route.path === path,
diff --git a/package.json b/package.json
index 8e7e2baec..b4e3ebe9c 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"e2e": "cypress run",
"e2e:open": "cypress open",
"dev:e2e": "server-test dev :3000 e2e:open",
- "pretty-quick": "pretty-quick --pattern \"**/*.*(html|js|json|vue)\"",
+ "pretty-quick": "pretty-quick --staged --pattern \"**/*.*(html|js|json|vue)\"",
"test": "start-server-and-test start http-get://localhost:3000 e2e"
},
"husky": {
diff --git a/pages/graphql.vue b/pages/graphql.vue
index e2b5f7c37..4d07a1022 100644
--- a/pages/graphql.vue
+++ b/pages/graphql.vue
@@ -153,7 +153,10 @@