├── .browserslistrc
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── deploy.sh
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
└── index.html
├── server.js
├── src
├── App.vue
├── assets
│ └── css
│ │ └── style.css
├── components
│ ├── Menu.vue
│ ├── PageNotFound.vue
│ └── SocialLogin.vue
├── config
│ ├── facebook_oAuth.js
│ ├── google_oAuth.js
│ └── utils.js
├── main.js
├── registerServiceWorker.js
├── router
│ └── router.js
├── store
│ └── store.js
└── views
│ ├── Home.vue
│ ├── Login.vue
│ └── SignUp.vue
└── tests
└── unit
├── .eslintrc.js
└── example.spec.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | '@vue/standard'
9 | ],
10 | rules: {
11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
13 | },
14 | parserOptions: {
15 | parser: 'babel-eslint'
16 | },
17 | overrides: [
18 | {
19 | files: [
20 | '**/__tests__/*.{j,t}s?(x)'
21 | ],
22 | env: {
23 | mocha: true
24 | }
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | package-lock.json
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Signup with Facebook / Google using Vue
2 |
3 | Handling SignUp or SignIn with Google and Facebook using Pure VueJS applications without any external package.
4 |
5 | ## Project setup
6 | ```
7 | npm install
8 | ```
9 |
10 | ## Google Setup Client ID
11 |
12 | import GoogleAuth from '@/config/google.js'
13 | const gauthOption = {
14 | clientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
15 | scope: 'profile email',
16 | prompt: 'select_account'
17 | }
18 | Vue.use(GoogleAuth, gauthOption)
19 |
20 |
21 | ## Options
22 |
23 |
24 |
25 |
26 | Property
27 | Type
28 | Required
29 | Description
30 |
31 |
32 |
33 |
34 | clientId
35 | String
36 | Required.
37 | The app's client ID, found and created in the Google Developers Console.
38 |
39 |
40 | scope
41 | String
42 | Optional.
43 | Default value is profile email
. Full list of scopes .
44 |
45 |
46 | prompt
47 | String
48 | Optional.
49 | This value using for authCode. The possible values are select_account
or consent
. Default value is select_account
. To get refresh token from auth code, use consent
.
50 |
51 |
52 | fetch_basic_profile
53 | Boolean
54 | Optional.
55 | If set to true, email profile openid
will be automatically added as scope . Default value is true
.
56 |
57 |
58 |
59 |
60 | ## Methods
61 |
62 |
63 |
64 |
65 | Property
66 | Description
67 | Type
68 |
69 |
70 |
71 |
72 | GoogleAuth
73 | return of gapi.auth2.getAuthInstance()
74 | Object
75 |
76 |
77 | isAuthorized
78 | Whether or not you have auth
79 | Boolean
80 |
81 |
82 | isInit
83 | Whether or not api init
84 | Boolean
85 |
86 |
87 | isLoaded
88 | Whether or not api init. will be deprecated.
89 | Function
90 |
91 |
92 | signIn
93 | function for sign-in
94 | Function
95 |
96 |
97 | getAuthCode
98 | function for getting authCode
99 | Function
100 |
101 |
102 | signOut
103 | function for sign-out
104 | Function
105 |
106 |
107 |
108 |
109 | ## Usage
110 |
111 | We already initalized GoogleAuth and directly we can add click event for the login button as below,
112 |
113 | loginWithGoogle () {
114 | this.$gAuth
115 | .signIn()
116 | .then(GoogleUser => {
117 | // on success do something
118 | console.log('GoogleUser', GoogleUser)
119 | console.log('getId', GoogleUser.getId())
120 | console.log('getBasicProfile', GoogleUser.getBasicProfile())
121 | console.log('getAuthResponse', GoogleUser.getAuthResponse())
122 | })
123 | .catch(error => {
124 | console.log('error', error)
125 | })
126 | }
127 |
128 | ## Facebook App ID Setup
129 | Important: The Facebook SDK must first be loaded asynchronously for the plugin to work. Something like this will do:
130 |
131 | export const initFbsdk = () => {
132 | return new Promise(resolve => {
133 | window.fbAsyncInit = function() {
134 | FB.init({
135 | appId : 'xxxxxxxxxxxxxxxxxxx',
136 | cookie : true, // enable cookies to allow the server to access the session
137 | xfbml : true, // parse social plugins on this page
138 | version : 'v2.8' // use graph api version 2.8
139 | });
140 | };
141 | (function(d, s, id) {
142 | var js, fjs = d.getElementsByTagName(s)[0];
143 | if (d.getElementById(id)) return;
144 | js = d.createElement(s); js.id = id;
145 | js.src = "//connect.facebook.net/en_US/sdk.js";
146 | fjs.parentNode.insertBefore(js, fjs);
147 | }(document, 'script', 'facebook-jssdk'));
148 | })
149 | }
150 |
151 | If you're not in a modular environment, just include it as a
.
152 |
153 |
154 |
155 | ### Usage
156 | Step 1: import and use the plugin if you're in a modular environment otherwise plugin will register itself.
157 |
158 | import { initFbsdk } from '@/config/facebook_oAuth.js'
159 |
160 | Step 2: Initialize the Facebook instance with the app id
161 |
162 | mounted () {
163 | initFbsdk()
164 | }
165 | Step 3: Add the button click event
166 |
167 | loginWithFacebook () {
168 | window.FB.login(response => {
169 | console.log('fb response', response)
170 | }, this.params)
171 | }
172 |
173 | ### Compiles and hot-reloads for development
174 | ```
175 | npm run serve
176 | ```
177 |
178 | ## [Demo Link](https://young-savannah-57214.herokuapp.com/login)
179 | # Login Screen
180 |
181 |
182 |
183 |
184 | # SignUp Screen
185 |
186 |
187 |
188 | # Facebook with SignUp/SignIn
189 |
190 |
191 | # Google with SignUp/SignIn
192 |
193 |
194 | ### Compiles and minifies for production
195 | ```
196 | npm run build
197 | ```
198 |
199 | ### Run your tests
200 | ```
201 | npm run test
202 | ```
203 |
204 | ### Lints and fixes files
205 | ```
206 | npm run lint
207 | ```
208 |
209 | ### Run your unit tests
210 | ```
211 | npm run test:unit
212 | ```
213 |
214 | ### Customize configuration
215 | See [Configuration Reference](https://cli.vuejs.org/config/).
216 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | # abort on errors
3 | set -e
4 | # build
5 | npm run build
6 | # navigate into the build output directory
7 | cd dist
8 | # if you are deploying to a custom domain
9 | # echo 'www.example.com' > CNAME
10 | git init
11 | git add -A
12 | git commit -m 'deploy'
13 | git push -f git@github.com/Jebasuthan/Vue-Facebook-Google-oAuth.git master:gh-pages
14 | cd -
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "signup_with_facebook_google_vue",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "postinstall": "if test \"$NODE_ENV\" = \"production\" ; then npm run build ; fi ",
7 | "start": "HTTPS=true node server.js",
8 | "serve": "vue-cli-service serve",
9 | "build": "vue-cli-service build",
10 | "lint": "vue-cli-service lint",
11 | "test:unit": "vue-cli-service test:unit",
12 | "deploy": "sh deploy.sh"
13 | },
14 | "dependencies": {
15 | "connect-history-api-fallback": "^1.6.0",
16 | "core-js": "^2.6.5",
17 | "express": "^4.17.1",
18 | "register-service-worker": "^1.6.2",
19 | "vue": "^2.6.10",
20 | "vue-router": "^3.0.3",
21 | "vuex": "^3.0.1"
22 | },
23 | "devDependencies": {
24 | "@vue/cli-plugin-babel": "^3.11.0",
25 | "@vue/cli-plugin-eslint": "^3.11.0",
26 | "@vue/cli-plugin-unit-mocha": "^3.11.0",
27 | "@vue/cli-service": "^3.11.0",
28 | "@vue/eslint-config-standard": "^4.0.0",
29 | "@vue/test-utils": "1.0.0-beta.29",
30 | "babel-eslint": "^10.0.1",
31 | "chai": "^4.1.2",
32 | "eslint": "^5.16.0",
33 | "eslint-plugin-vue": "^5.0.0",
34 | "vue-template-compiler": "^2.6.10"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jebasuthan/Vue-Facebook-Google-oAuth/0433de43d331b8375a628e1733392ce2500381dd/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Signup With Facebook Google Using Vue
10 |
11 |
12 |
13 | We're sorry but Signup With Facebook Google Using Vue doesn't work properly without JavaScript enabled. Please enable it to continue.
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const path = require('path');
3 | const history = require('connect-history-api-fallback');
4 |
5 | const app = express();
6 | const staticFileMiddleware = express.static(path.join(__dirname + '/dist'));
7 |
8 | app.use(staticFileMiddleware);
9 | app.use(history({
10 | disableDotRule: true,
11 | verbose: true
12 | }));
13 | app.use(staticFileMiddleware);
14 |
15 | app.get('/', function (req, res) {
16 | res.render(path.join(__dirname + '/dist/index.html'));
17 | });
18 |
19 | var server = app.listen(process.env.PORT || 8080, function () {
20 | var port = server.address().port;
21 | console.log("App now running on port", port);
22 | });
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
--------------------------------------------------------------------------------
/src/assets/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: Arial, Helvetica, sans-serif;
3 | font-size: 14px;
4 | background: #0069ff;
5 | }
6 | /* Style the tab */
7 | .tab {
8 | overflow: hidden;
9 | border: 1px solid #ccc;
10 | background-color: #f1f1f1;
11 | }
12 | /* Style the buttons inside the tab */
13 | .tab a {
14 | background-color: inherit;
15 | float: right;
16 | cursor: pointer;
17 | padding: 14px 16px;
18 | transition: 0.3s;
19 | font-size: 17px;
20 | text-decoration: none;
21 | border: 1px solid;
22 | }
23 | /* Change background color of buttons on hover */
24 | .tab a:hover {
25 | background-color: #ddd;
26 | }
27 | /* Create an active/current tablink class */
28 | .tab a.active {
29 | background-color: #ccc;
30 | }
31 | /* Style the tab content */
32 | .tabcontent {
33 | display: none;
34 | padding: 6px 12px;
35 | border: 1px solid #ccc;
36 | border-top: none;
37 | }
38 | .loginsuccess-container {
39 | padding: 20px;
40 | margin: 0 auto;
41 | width: 80%;
42 | box-shadow: beige;
43 | border: 1px solid #ccc;
44 | border-radius: 5px;
45 | background: #fff;
46 | word-break: break-all;
47 | }
48 | .main-container {
49 | margin-top: 10%;
50 | }
51 | .box-container {
52 | padding: 20px;
53 | margin: 0 auto;
54 | width: 400px;
55 | box-shadow: beige;
56 | border: 1px solid #ccc;
57 | border-radius: 5px;
58 | background: #fff;
59 | }
60 | .heading {
61 | text-align: center;
62 | font-weight: 300;
63 | color: #444;
64 | margin: 0 auto 45px;
65 | font-size: 35px;
66 | line-height: 38px;
67 | text-transform: none;
68 | letter-spacing: 0;
69 | }
70 | .form-fields, .form-fields button {
71 | width: 100%;
72 | margin: 5px 0;
73 | line-height: 28px;
74 | border-radius: 5px;
75 | }
76 | .form-fields input {
77 | width: 100%;
78 | line-height: 40px;
79 | border-radius: 5px;
80 | border-radius: 5px;
81 | border: 1px solid #f1f1f1;
82 | background: #fff;
83 | padding: 0 5px;
84 | font-size: 14px;
85 | }
86 | .signIn {
87 | padding: 10px 32px;
88 | color: white;
89 | font-size: 16px;
90 | font-weight: 400;
91 | background: #15CD72;
92 | text-align: center;
93 | cursor: pointer;
94 | height: auto;
95 | -webkit-appearance: none;
96 | }
97 | .createaccount {
98 | padding: 15px;
99 | background-color: #0069ff;
100 | border: none;
101 | color: #fff;
102 | font-size: 16px;
103 | font-weight: 400;
104 | height: 48px;
105 | line-height: 48px;
106 | padding: 0 32px;
107 | text-align: center;
108 | border-radius: 5px;
109 | }
110 | .center {
111 | text-align: center
112 | }
113 | .login-choice span {
114 | color: #5b6987;
115 | display: -ms-grid;
116 | display: grid;
117 | font-size: 16px;
118 | width: 100%;
119 | line-height: 40px;
120 | -webkit-box-align: center;
121 | -ms-flex-align: center;
122 | align-items: center;
123 | text-align: center;
124 | -ms-grid-columns: minmax(20px,1fr) auto minmax(20px,1fr);
125 | grid-template-columns: minmax(20px,1fr) auto minmax(20px,1fr);
126 | grid-gap: 19px;
127 | }
128 | .login-choice span:after, .login-choice span:before {
129 | content: "";
130 | border-top: 1px solid #e5e8ed;
131 | }
132 | .signup-buttons {
133 | margin-top: 15px;
134 | display: -webkit-box;
135 | display: -ms-flexbox;
136 | display: flex;
137 | -webkit-box-pack: justify;
138 | -ms-flex-pack: justify;
139 | justify-content: space-between;
140 | position: relative;
141 | }
142 | .facebook-signup, .google-signup {
143 | color: #031b4e;
144 | background: #f2f8ff;
145 | border: 1px solid rgba(0,105,255,.2);
146 | -webkit-box-sizing: border-box;
147 | box-sizing: border-box;
148 | border-radius: 3px;
149 | display: inline-block;
150 | margin-top: 0;
151 | width: 47.5%;
152 | padding: 15px;
153 | text-align: center;
154 | position: inherit;
155 | }
156 | .signup-buttons a {
157 | vertical-align: middle;
158 | text-decoration: none;
159 | }
160 | .signup-buttons svg {
161 | left: 16px;
162 | position: absolute;
163 | top: 50%;
164 | -webkit-transform: translateY(-50%);
165 | transform: translateY(-50%);
166 | }
167 | .footer, .footer a {
168 | text-align: center;
169 | color: #fff
170 | }
--------------------------------------------------------------------------------
/src/components/Menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Logout
4 |
Sign In
5 |
Sign Up
6 |
7 |
8 |
9 |
23 |
--------------------------------------------------------------------------------
/src/components/PageNotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
404 Page not Found
4 |
Go Back to Login
5 |
6 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/src/components/SocialLogin.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
84 |
--------------------------------------------------------------------------------
/src/config/facebook_oAuth.js:
--------------------------------------------------------------------------------
1 | export const initFbsdk = () => {
2 | return new Promise(resolve => {
3 | window.fbAsyncInit = function() {
4 | FB.init({
5 | appId: '2507113472858546',
6 | cookie: true, // enable cookies to allow the server to access the session
7 | xfbml: true, // parse social plugins on this page
8 | version: 'v2.8' // use graph api version 2.8
9 | })
10 | }(function (d, s, id) {
11 | var js, fjs = d.getElementsByTagName(s)[0]
12 | if (d.getElementById(id)) return
13 | js = d.createElement(s); js.id = id
14 | js.src = '//connect.facebook.net/en_US/all.js'
15 | fjs.parentNode.insertBefore(js, fjs)
16 | }(document, 'script', 'facebook-jssdk'))
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/src/config/google_oAuth.js:
--------------------------------------------------------------------------------
1 | var googleAuth = (function () {
2 | function installClient () {
3 | var apiUrl = 'https://apis.google.com/js/api.js'
4 | return new Promise((resolve) => {
5 | var script = document.createElement('script')
6 | script.src = apiUrl
7 | script.onreadystatechange = script.onload = function () {
8 | if (!script.readyState || /loaded|complete/.test(script.readyState)) {
9 | setTimeout(function () {
10 | resolve()
11 | }, 500)
12 | }
13 | }
14 | document.getElementsByTagName('head')[0].appendChild(script)
15 | })
16 | }
17 |
18 | function initClient (config) {
19 | return new Promise((resolve) => {
20 | window.gapi.load('auth2', () => {
21 | window.gapi.auth2.init(config)
22 | .then(() => {
23 | resolve(window.gapi)
24 | })
25 | })
26 | })
27 | }
28 |
29 | function Auth () {
30 | if (!(this instanceof Auth))
31 | return new Auth()
32 | this.GoogleAuth = null /* window.gapi.auth2.getAuthInstance() */
33 | this.isAuthorized = false
34 | this.isInit = false
35 | this.prompt = null
36 | this.isLoaded = function () {
37 | /* eslint-disable */
38 | console.warn('isLoaded() will be deprecated. You can use "this.$gAuth.isInit"')
39 | return !!this.GoogleAuth
40 | }
41 |
42 | this.load = (config, prompt) => {
43 | installClient()
44 | .then(() => {
45 | return initClient(config)
46 | })
47 | .then((gapi) => {
48 | this.GoogleAuth = gapi.auth2.getAuthInstance()
49 | this.isInit = true
50 | this.prompt = prompt
51 | this.isAuthorized = this.GoogleAuth.isSignedIn.get()
52 | })
53 | }
54 |
55 | this.signIn = (successCallback, errorCallback) => {
56 | return new Promise((resolve, reject) => {
57 | if (!this.GoogleAuth) {
58 | if (typeof errorCallback === 'function') errorCallback(false)
59 | reject(false)
60 | return
61 | }
62 | this.GoogleAuth.signIn()
63 | .then(googleUser => {
64 | if (typeof successCallback === 'function') successCallback(googleUser)
65 | this.isAuthorized = this.GoogleAuth.isSignedIn.get()
66 | resolve(googleUser)
67 | })
68 | .catch(error => {
69 | if (typeof errorCallback === 'function') errorCallback(error)
70 | reject(error)
71 | })
72 | })
73 | }
74 |
75 | this.getAuthCode = (successCallback, errorCallback) => {
76 | return new Promise((resolve, reject) => {
77 | if (!this.GoogleAuth) {
78 | if (typeof errorCallback === 'function') errorCallback(false)
79 | reject(false)
80 | return
81 | }
82 | this.GoogleAuth.grantOfflineAccess({ prompt: this.prompt })
83 | .then(function (resp) {
84 | if (typeof successCallback === 'function') successCallback(resp.code)
85 | resolve(resp.code)
86 | })
87 | .catch(function (error) {
88 | if (typeof errorCallback === 'function') errorCallback(error)
89 | reject(error)
90 | })
91 | })
92 | }
93 |
94 | this.signOut = (successCallback, errorCallback) => {
95 | return new Promise((resolve, reject) => {
96 | if (!this.GoogleAuth) {
97 | if (typeof errorCallback === 'function') errorCallback(false)
98 | reject(false)
99 | return
100 | }
101 | this.GoogleAuth.signOut()
102 | .then(() => {
103 | if (typeof successCallback === 'function') successCallback()
104 | this.isAuthorized = false
105 | resolve(true)
106 | })
107 | .catch(error => {
108 | if (typeof errorCallback === 'function') errorCallback(error)
109 | reject(error)
110 | })
111 | })
112 | }
113 | }
114 |
115 | return new Auth()
116 | })()
117 |
118 | function installGoogleAuthPlugin(Vue, options) {
119 | //set config
120 | let GoogleAuthConfig = null
121 | let GoogleAuthDefaultConfig = { scope: 'profile email', discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'] }
122 | let prompt = 'select_account'
123 | if (typeof options === 'object') {
124 | GoogleAuthConfig = Object.assign(GoogleAuthDefaultConfig, options)
125 | if (options.scope) GoogleAuthConfig.scope = options.scope
126 | if (options.prompt) prompt = options.prompt
127 | if (!options.clientId) {
128 | console.warn('clientId is required')
129 | }
130 | } else {
131 | console.warn('invalid option type. Object type accepted only')
132 | }
133 |
134 | //Install Vue plugin
135 | Vue.gAuth = googleAuth
136 | Object.defineProperties(Vue.prototype, {
137 | $gAuth: {
138 | get: function () {
139 | return Vue.gAuth
140 | }
141 | }
142 | })
143 | Vue.gAuth.load(GoogleAuthConfig, prompt)
144 | }
145 |
146 | export default installGoogleAuthPlugin
--------------------------------------------------------------------------------
/src/config/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Set localStorage
3 | */
4 | export const setStore = (name, content) => {
5 | if (!name) return
6 | if (typeof content !== 'string') {
7 | content = JSON.stringify(content)
8 | }
9 | return window.localStorage.setItem(name, content)
10 | }
11 | /**
12 | * Get localStorage
13 | */
14 | export const getStore = (name) => {
15 | if (!name) return
16 | return JSON.parse(window.localStorage.getItem(name))
17 | }
18 | /**
19 | * Clear localStorage
20 | */
21 | export const removeItem = (name) => {
22 | if (!name) return
23 | return window.localStorage.removeItem(name)
24 | }
25 | /**
26 | * Validate Email address
27 | */
28 | export const isValidEmail = (value) => {
29 | return value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,64}$/i.test(value) ? false : true
30 | }
31 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router/router'
4 | import store from './store/store'
5 |
6 | import '@/assets/css/style.css'
7 | import './registerServiceWorker'
8 |
9 | import GoogleAuth from '@/config/google_oAuth.js'
10 | const gauthOption = {
11 | clientId: '707231563844-e5cpkqrlt62gncmj6b84of5sml9lp8g9.apps.googleusercontent.com',
12 | scope: 'profile email',
13 | prompt: 'select_account'
14 | }
15 | Vue.use(GoogleAuth, gauthOption)
16 | Vue.config.productionTip = false
17 |
18 | new Vue({
19 | router,
20 | store,
21 | render: h => h(App)
22 | }).$mount('#app')
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 |
3 | import { register } from "register-service-worker";
4 |
5 | if (process.env.NODE_ENV === "production") {
6 | register(`${process.env.BASE_URL}service-worker.js`, {
7 | ready() {
8 | console.log(
9 | "App is being served from cache by a service worker.\n" +
10 | "For more details, visit https://goo.gl/AFskqB"
11 | );
12 | },
13 | cached() {
14 | console.log("Content has been cached for offline use.");
15 | },
16 | updated() {
17 | console.log("New content is available; please refresh.");
18 | },
19 | offline() {
20 | console.log(
21 | "No internet connection found. App is running in offline mode."
22 | );
23 | },
24 | error(error) {
25 | console.error("Error during service worker registration:", error);
26 | }
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/src/router/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Home from '@/views/Home'
4 | import Login from '@/views/Login'
5 | import SignUp from '@/views/SignUp'
6 | import PageNotFound from '@/components/PageNotFound'
7 |
8 | Vue.use(Router)
9 |
10 | let baseRoutes = [
11 | {
12 | path: '/',
13 | redirect: '/login'
14 | },
15 | {
16 | path: '/home',
17 | name: 'Home',
18 | component: Home
19 | },
20 | {
21 | path: '/login',
22 | name: 'Login',
23 | component: Login
24 | },
25 | {
26 | path: '/signup',
27 | name: 'SignUp',
28 | component: SignUp
29 | },
30 | {
31 | path: '*',
32 | name: 'PageNotFound',
33 | component: PageNotFound
34 | }
35 | ]
36 |
37 | const router = new Router({
38 | mode: 'history',
39 | linkExactActiveClass: 'active',
40 | base: process.env.BASE_URL,
41 | routes: baseRoutes
42 | })
43 |
44 | router.beforeEach((to, from, next) => {
45 | // redirect to login page if not logged in and trying to access a restricted page
46 | const publicPages = ['/login', '/signup']
47 | const authRequired = !publicPages.includes(to.path)
48 | const loggedIn = localStorage.getItem('user')
49 | if (authRequired && !loggedIn) {
50 | return next('/login')
51 | }
52 | next()
53 | })
54 |
55 | export default router
56 |
--------------------------------------------------------------------------------
/src/store/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import { setStore, getStore } from '@/config/utils'
4 |
5 | Vue.use(Vuex)
6 |
7 | const user = getStore('user')
8 |
9 | export default new Vuex.Store({
10 | state: {
11 | loginUser: user
12 | },
13 | mutations: {
14 | setLoginUser(state, user) {
15 | state.loginUser = user
16 | setStore('user', user)
17 | }
18 | },
19 | actions: {
20 |
21 | },
22 | getters: {
23 | getLoginUserInfo(state) {
24 | return state.loginUser
25 | }
26 | }
27 | })
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Login Success!
7 |
8 |
9 |
10 |
Welcome {{this.$store.state.loginUser.fb.user && this.$store.state.loginUser.fb.user.name}} !
11 |
12 |
Facebook Access Token- {{this.$store.state.loginUser.fb && this.$store.state.loginUser.fb.auth.accessToken}}
13 |
14 |
15 |
16 |
17 |
Welcome {{this.$store.state.loginUser.google.user.name}} !
18 |
19 |
20 |
Google Access Token- {{this.$store.state.loginUser.google.auth.access_token}}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
39 |
--------------------------------------------------------------------------------
/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
36 |
--------------------------------------------------------------------------------
/src/views/SignUp.vue:
--------------------------------------------------------------------------------
1 |
2 |
36 |
37 |
38 |
47 |
--------------------------------------------------------------------------------
/tests/unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | mocha: true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/tests/unit/example.spec.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import { shallowMount } from '@vue/test-utils'
3 | import HelloWorld from '@/components/HelloWorld.vue'
4 |
5 | describe('HelloWorld.vue', () => {
6 | it('renders props.msg when passed', () => {
7 | const msg = 'new message'
8 | const wrapper = shallowMount(HelloWorld, {
9 | propsData: { msg }
10 | })
11 | expect(wrapper.text()).to.include(msg)
12 | })
13 | })
14 |
--------------------------------------------------------------------------------