Skip to content

Commit b42485e

Browse files
committed
add authentication
1 parent d67b526 commit b42485e

File tree

6 files changed

+258
-44
lines changed

6 files changed

+258
-44
lines changed

vue-noob-3/public/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
href="https://fonts.googleapis.com/icon?family=Material+Icons"
1515
rel="stylesheet"
1616
/>
17+
<link
18+
href="https://fonts.googleapis.com/icon?family=Material+Icons"
19+
rel="stylesheet"
20+
/>
1721
</head>
1822
<body>
1923
<noscript>
Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,65 @@
11
<template>
2-
<nav class="indigo lighten-1">
3-
<div class="nav-wrapper">
4-
<router-link to="/" class="brand-logo center">Employee Manager</router-link>
2+
<nav class="green lighten-1">
3+
<div class="container">
4+
<div class="nav-wrapper">
5+
<router-link to="/" class="brand-logo">Employee Manager</router-link>
6+
<ul id="nav-mobile" class="right hide-on-med-and-down">
7+
<div v-if="isAuthenticated">
8+
<li>
9+
<router-link class="black-text" to="/">Dashboard</router-link>
10+
</li>
11+
<li class="email black-text">{{ isAuthenticated.email }}</li>
12+
<li>
13+
<button @click="signOut" class="btn-flat indigo white-text">logout</button>
14+
</li>
15+
</div>
16+
<li v-if="!isAuthenticated">
17+
<router-link class="black-text" to="/auth">Authenticate</router-link>
18+
</li>
19+
</ul>
20+
</div>
521
</div>
622
</nav>
723
</template>
824

925
<script>
26+
import { firebaseApp } from "@/firebase";
27+
import M from "materialize-css/dist/js/materialize";
1028
export default {
11-
name: "app-navbar"
29+
name: "app-navbar",
30+
data() {
31+
return {
32+
isAuthenticated: null,
33+
};
34+
},
35+
beforeMount() {
36+
const vm = this;
37+
firebaseApp.auth().onAuthStateChanged((user) => {
38+
vm.isAuthenticated = user;
39+
});
40+
},
41+
methods: {
42+
signOut: async function () {
43+
if (firebaseApp.auth().currentUser) {
44+
try {
45+
await firebaseApp.auth().signOut();
46+
M.toast({ html: "You are Signed out !" });
47+
this.$router.push("/auth");
48+
} catch (e) {
49+
return M.toast({ html: e.message });
50+
}
51+
}
52+
},
53+
},
1254
};
1355
</script>
1456

1557
<style scoped>
58+
.email.black-text {
59+
letter-spacing: 0.5px;
60+
margin-right: 15px;
61+
}
62+
.black-text {
63+
font-size: 1.1em;
64+
}
1665
</style>

vue-noob-3/src/firebase/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import firebase from 'firebase/app';
22
import 'firebase/firestore';
3+
import 'firebase/auth';
34
import firebaseConfig from './config';
45

5-
const firebaseApp = firebase.initializeApp(firebaseConfig);
6+
export const firebaseApp = firebase.initializeApp(firebaseConfig);
67
export default firebaseApp.firestore();

vue-noob-3/src/main.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
import Vue from 'vue'
2-
import App from './App.vue'
3-
import router from './router'
1+
import Vue from 'vue';
2+
import App from './App.vue';
3+
import router from './router';
4+
import { firebaseApp } from '@/firebase';
45

5-
Vue.config.productionTip = false
6+
Vue.config.productionTip = false;
67

7-
new Vue({
8-
router,
9-
render: h => h(App)
10-
}).$mount('#app')
8+
let app;
9+
10+
firebaseApp.auth().onAuthStateChanged(function() {
11+
if (!app) {
12+
app = new Vue({
13+
router,
14+
render: h => h(App),
15+
}).$mount('#app');
16+
}
17+
});

vue-noob-3/src/router/index.js

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,82 @@
1-
import Vue from 'vue'
2-
import VueRouter from 'vue-router'
3-
import Home from '../views/Home.vue'
4-
import AddEmployee from '../views/Add.vue'
5-
import ViewEmployee from '../views/About.vue';
1+
import Vue from 'vue';
2+
import VueRouter from 'vue-router';
3+
import Home from '../views/Home';
4+
import AddEmployee from '../views/Add';
5+
import ViewEmployee from '../views/About';
66
import EditEmployee from '../views/Edit';
7+
import Auth from '../views/Auth';
78

8-
Vue.use(VueRouter)
9+
Vue.use(VueRouter);
910

10-
const routes = [{
11-
path: '/',
12-
name: 'Home',
13-
component: Home
14-
},
15-
{
16-
path: '/add',
17-
name: 'AddEmployee',
18-
component: AddEmployee
19-
},
20-
{
21-
path: '/view/:id',
22-
name: 'ViewEmployee',
23-
component: ViewEmployee
24-
},
25-
{
26-
path: '/edit/:id',
27-
name: 'EditEmployee',
28-
component: EditEmployee
29-
}
30-
]
11+
const routes = [
12+
{
13+
path: '/',
14+
name: 'Home',
15+
component: Home,
16+
meta: {
17+
requiresAuth: true,
18+
},
19+
},
20+
{
21+
path: '/add',
22+
name: 'AddEmployee',
23+
component: AddEmployee,
24+
meta: {
25+
requiresAuth: true,
26+
},
27+
},
28+
{
29+
path: '/view/:id',
30+
name: 'ViewEmployee',
31+
component: ViewEmployee,
32+
meta: {
33+
requiresAuth: true,
34+
},
35+
},
36+
{
37+
path: '/edit/:id',
38+
name: 'EditEmployee',
39+
component: EditEmployee,
40+
meta: {
41+
requiresAuth: true,
42+
},
43+
},
44+
{
45+
path: '/auth',
46+
name: Auth,
47+
component: Auth,
48+
meta: { requiresGuest: true },
49+
},
50+
];
3151

3252
const router = new VueRouter({
33-
routes,
34-
mode: 'history'
35-
})
53+
routes,
54+
mode: 'history',
55+
});
56+
import { firebaseApp } from '@/firebase';
3657

37-
export default router
58+
router.beforeEach((to, from, next) => {
59+
if (to.matched.some(record => record.meta.requiresAuth)) {
60+
if (firebaseApp.auth().currentUser) {
61+
next();
62+
} else {
63+
next({
64+
path: '/auth',
65+
query: { redirect: to.fullPath.split('/')[1] },
66+
});
67+
}
68+
} else if (to.matched.some(record => record.meta.requiresGuest)) {
69+
if (firebaseApp.auth().currentUser) {
70+
next({
71+
path: from.fullPath,
72+
query: { redirect: to.fullPath.split('/')[1] },
73+
});
74+
} else {
75+
next();
76+
}
77+
} else {
78+
next();
79+
}
80+
});
81+
82+
export default router;

vue-noob-3/src/views/Auth.vue

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<template>
2+
<div class="container z-depth-1">
3+
<div class="row">
4+
<h4 class="center red-text">{{ mode.toUpperCase() }}</h4>
5+
<form @submit.prevent="handleSubmit" class="col s12">
6+
<div class="row">
7+
<div class="input-field col s12">
8+
<i class="material-icons prefix">email</i>
9+
<input required v-model="email" type="email" class="validate" />
10+
<label for="icon_prefix">Email Address</label>
11+
</div>
12+
</div>
13+
<div class="row">
14+
<div class="input-field col s12">
15+
<i class="material-icons prefix">security</i>
16+
<input minlength="6" v-model="password" type="password" class="validate" />
17+
<label for="icon_prefix">Password</label>
18+
</div>
19+
</div>
20+
<div class="row">
21+
<div class="input-field col s12">
22+
<button class="btn green waves-effect waves-light" type="submit">
23+
{{ submitted ? 'loading...' : mode }}
24+
<i class="material-icons right">send</i>
25+
</button>
26+
<button
27+
type="button"
28+
style="margin-left: 1em"
29+
class="btn teal"
30+
@click="mode = mode === 'login' ? 'register' : 'login'"
31+
>Switch to {{mode === 'login' ? 'register' : 'login'}}</button>
32+
</div>
33+
</div>
34+
</form>
35+
</div>
36+
</div>
37+
</template>
38+
39+
<script>
40+
import { firebaseApp } from "@/firebase";
41+
import M from "materialize-css/dist/js/materialize";
42+
export default {
43+
name: "AppAuthPage",
44+
data() {
45+
return {
46+
email: "",
47+
password: "",
48+
mode: "login",
49+
submitted: false,
50+
};
51+
},
52+
methods: {
53+
handleSubmit: async function () {
54+
this.submitted = true;
55+
if (!this.validateEmail(this.email)) {
56+
this.submitted = false;
57+
return M.toast({ html: "Please enter a valid Email Address" });
58+
}
59+
const err = await this.handleAuth();
60+
if (err) {
61+
this.submitted = false;
62+
return M.toast({ html: err.message });
63+
}
64+
M.toast({ html: `You are Logged in as ${this.email}` });
65+
this.email = "";
66+
this.password = "";
67+
this.$router.push("/");
68+
},
69+
handleAuth: async function () {
70+
if (this.mode === "login") {
71+
try {
72+
await firebaseApp
73+
.auth()
74+
.signInWithEmailAndPassword(this.email, this.password);
75+
} catch (e) {
76+
return e;
77+
}
78+
} else if (this.mode === "register") {
79+
try {
80+
await firebaseApp
81+
.auth()
82+
.createUserWithEmailAndPassword(this.email, this.password);
83+
} catch (e) {
84+
return e;
85+
}
86+
}
87+
},
88+
validateEmail(email) {
89+
const reg = new RegExp(
90+
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
91+
);
92+
return reg.test(email);
93+
},
94+
},
95+
};
96+
</script>
97+
98+
<style scoped>
99+
.container.z-depth-1 {
100+
padding: 10px 1em 0 1em;
101+
margin-top: 3em;
102+
}
103+
@media screen and (min-width: 1024px) {
104+
.container.z-depth-1 {
105+
width: 60%;
106+
}
107+
}
108+
</style>

0 commit comments

Comments
 (0)