Merge pull request #47 from 0hAodha/userAccounts
Implement CRUD operations on user accounts
This commit is contained in:
@ -42,6 +42,7 @@ exports.postStationData = functions.https.onRequest((request, response) => {
|
|||||||
|
|
||||||
// helper function to write to the database
|
// helper function to write to the database
|
||||||
function batchWriteDB(request, response, db, jsonData, dartCodes, stationTypeCode) {
|
function batchWriteDB(request, response, db, jsonData, dartCodes, stationTypeCode) {
|
||||||
|
if (!jsonData) return
|
||||||
response.set('Access-Control-Allow-Origin', '*');
|
response.set('Access-Control-Allow-Origin', '*');
|
||||||
response.set('Access-Control-Allow-Credentials', 'true');
|
response.set('Access-Control-Allow-Credentials', 'true');
|
||||||
|
|
||||||
@ -136,6 +137,7 @@ exports.postLiveTrainData = functions.https.onRequest((request, response) => {
|
|||||||
|
|
||||||
// helper function to write to the database
|
// helper function to write to the database
|
||||||
function batchWriteDB(request, response, db, jsonData, trainTypeCode) {
|
function batchWriteDB(request, response, db, jsonData, trainTypeCode) {
|
||||||
|
if (!jsonData) return
|
||||||
response.set('Access-Control-Allow-Origin', '*');
|
response.set('Access-Control-Allow-Origin', '*');
|
||||||
response.set('Access-Control-Allow-Credentials', 'true');
|
response.set('Access-Control-Allow-Credentials', 'true');
|
||||||
|
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
<a class="nav-link"><router-link to="/insights">Insights</router-link></a>
|
<a class="nav-link"><router-link to="/insights">Insights</router-link></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a v-if="!isLoggedIn" class="nav-link"><router-link to="/signup">Sign Up</router-link></a>
|
<a v-if="!isLoggedIn" class="nav-link"><router-link to="/login">Login</router-link></a>
|
||||||
<a v-if="isLoggedIn" class="nav-link"><router-link to="/secure">Secure</router-link></a>
|
<a v-if="isLoggedIn" class="nav-link"><router-link to="/account">Account Settings</router-link></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a v-if="isLoggedIn" class="nav-link"><router-link style="text-decoration: none; color: black; font-weight: 100;" @click="logout" to="/" class="navlink">Logout</router-link></a>
|
<a v-if="isLoggedIn" class="nav-link"><router-link style="text-decoration: none; color: black; font-weight: 100;" @click="logout" to="/" class="navlink">Logout</router-link></a>
|
||||||
<a v-if="!isLoggedIn" class="nav-link"><router-link to="/login">Login</router-link></a>
|
<a v-if="!isLoggedIn" class="nav-link"><router-link to="/signup">Sign Up</router-link></a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
165
src/pages/AccountPage.vue
Normal file
165
src/pages/AccountPage.vue
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<template>
|
||||||
|
<Navbar />
|
||||||
|
<h1>Account Settings</h1>
|
||||||
|
<p>Your Email: {{ displayEmail }}</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p>Enter your current password to edit account settings</p>
|
||||||
|
<input type="password" v-model="currentPassword" placeholder="Enter existing password">
|
||||||
|
|
||||||
|
<h1>Change email</h1>
|
||||||
|
<input type="email" v-model="newEmail" aria-describedby="emailHelp" placeholder="Enter new email">
|
||||||
|
<input @click="updateUserEmail" type="submit" name="" value="Update Email">
|
||||||
|
|
||||||
|
<h1>Change password</h1>
|
||||||
|
<input type="password" v-model="newPassword" placeholder="Enter new password">
|
||||||
|
<input @click="updateUserPassword" type="submit" name="" value="Update Password">
|
||||||
|
|
||||||
|
<h1>Delete account</h1>
|
||||||
|
<input @click="deleteUserAccount" type="submit" name="" value="Delete Account">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p v-if="missingCredentials">Missing credentials to complete this action</p>
|
||||||
|
<p v-if="displayFirebaseSuccessMsg">{{ FirebaseSuccessMsg }}</p>
|
||||||
|
<p v-if="displayFirebaseError">{{ FirebaseError }}</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Navbar from '../components/Navbar.vue'
|
||||||
|
import app from '../api/firebase'
|
||||||
|
import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions"
|
||||||
|
import { getAuth, updateEmail, updatePassword, deleteUser, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth";
|
||||||
|
const auth = getAuth();
|
||||||
|
const user = auth.currentUser;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "AccountPage",
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Navbar,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
displayEmail: "",
|
||||||
|
newEmail: "",
|
||||||
|
newPassword: "",
|
||||||
|
currentPassword: "",
|
||||||
|
displayFirebaseSuccessMsg: false,
|
||||||
|
FirebaseSuccessMsg: "",
|
||||||
|
displayFirebaseError: false,
|
||||||
|
FirebaseError: "",
|
||||||
|
reAuthSuccessful: false,
|
||||||
|
missingCredentials: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
const user = auth.currentUser
|
||||||
|
this.displayEmail = user.email
|
||||||
|
|
||||||
|
|
||||||
|
const functions = getFunctions(app)
|
||||||
|
let host = window.location.hostname
|
||||||
|
if (host === '127.0.0.1' || host === 'localhost') {
|
||||||
|
connectFunctionsEmulator(functions, host, 5001);
|
||||||
|
}
|
||||||
|
const secureFunction = httpsCallable(functions, 'securefunction')
|
||||||
|
secureFunction().then((response) => {
|
||||||
|
console.log(response);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async authenticateUser(password) {
|
||||||
|
var credential = await EmailAuthProvider.credential(user.email, password)
|
||||||
|
await reauthenticateWithCredential(user, credential).then(() => {
|
||||||
|
this.reAuthSuccessful = true
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.reAuthSuccessful = false
|
||||||
|
this.FirebaseError = error.message
|
||||||
|
this.displayFirebaseError = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
resetMessages() {
|
||||||
|
this.missingCredentials = false
|
||||||
|
this.displayFirebaseError = false
|
||||||
|
this.displayFirebaseSuccessMsg = false
|
||||||
|
},
|
||||||
|
|
||||||
|
resetCredentials() {
|
||||||
|
this.newEmail = ""
|
||||||
|
this.newPassword = ""
|
||||||
|
this.currentPassword = ""
|
||||||
|
this.reAuthSuccessful = false
|
||||||
|
},
|
||||||
|
|
||||||
|
updateUserEmail() {
|
||||||
|
this.resetMessages()
|
||||||
|
if (!this.newEmail || !this.currentPassword) {
|
||||||
|
this.missingCredentials = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.authenticateUser(this.currentPassword).then(() => {
|
||||||
|
if (!this.reAuthSuccessful) return
|
||||||
|
updateEmail(user, this.newEmail).then(() => {
|
||||||
|
this.displayEmail = this.newEmail
|
||||||
|
this.resetCredentials()
|
||||||
|
this.FirebaseSuccessMsg = "Email updated"
|
||||||
|
this.displayFirebaseSuccessMsg = true
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.FirebaseError = error.message
|
||||||
|
this.displayFirebaseError = true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateUserPassword() {
|
||||||
|
this.resetMessages()
|
||||||
|
if (!this.newPassword || !this.currentPassword) {
|
||||||
|
this.missingCredentials = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.authenticateUser(this.currentPassword).then(() => {
|
||||||
|
if (!this.reAuthSuccessful) return
|
||||||
|
updatePassword(user, this.newPassword).then(() => {
|
||||||
|
this.resetCredentials()
|
||||||
|
this.FirebaseSuccessMsg = "Password updated"
|
||||||
|
this.displayFirebaseSuccessMsg = true
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.FirebaseError = error.message
|
||||||
|
this.displayFirebaseError = true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteUserAccount() {
|
||||||
|
this.resetMessages()
|
||||||
|
if (!this.currentPassword) {
|
||||||
|
this.missingCredentials = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.authenticateUser(this.currentPassword).then(() => {
|
||||||
|
if (!this.reAuthSuccessful) return
|
||||||
|
deleteUser(user).then(() => {
|
||||||
|
this.resetCredentials()
|
||||||
|
this.FirebaseSuccessMsg = "Account deleted"
|
||||||
|
this.displayFirebaseSuccessMsg = true
|
||||||
|
this.$router.push({path:'/'})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.FirebaseError = error.message
|
||||||
|
this.displayFirebaseError = true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
@ -11,6 +11,7 @@
|
|||||||
<input @click="login" type="submit" name="" value="Login">
|
<input @click="login" type="submit" name="" value="Login">
|
||||||
<a><router-link to="/signup">Don't have an account?</router-link></a>
|
<a><router-link to="/signup">Don't have an account?</router-link></a>
|
||||||
</div>
|
</div>
|
||||||
|
<p v-if="displayFirebaseError">{{ FirebaseError }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -25,7 +26,9 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: "",
|
email: "",
|
||||||
password: ""
|
password: "",
|
||||||
|
displayFirebaseError: false,
|
||||||
|
FirebaseError: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -35,17 +38,16 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
login() {
|
login() {
|
||||||
|
this.displayFirebaseError = false
|
||||||
const auth = getAuth(app)
|
const auth = getAuth(app)
|
||||||
signInWithEmailAndPassword(auth, this.email, this.password)
|
signInWithEmailAndPassword(auth, this.email, this.password)
|
||||||
.then((userCredential) => {
|
.then((userCredential) => {
|
||||||
const user = userCredential.user
|
const user = userCredential.user
|
||||||
this.$router.push({path:'/secure'})
|
this.$router.push({path:'/account'})
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
const errorCode = error.code
|
this.FirebaseError = error.message
|
||||||
const errorMessage = error.message
|
this.displayFirebaseError = true
|
||||||
console.log(errorCode)
|
|
||||||
console.log(errorMessage)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Navbar />
|
|
||||||
<h1>Secure</h1>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Navbar from '../components/Navbar.vue'
|
|
||||||
import app from '../api/firebase'
|
|
||||||
import {getFunctions, httpsCallable, connectFunctionsEmulator} from "firebase/functions"
|
|
||||||
export default {
|
|
||||||
name: "SecurePage",
|
|
||||||
|
|
||||||
components: {
|
|
||||||
Navbar,
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
const functions = getFunctions(app)
|
|
||||||
let host = window.location.hostname
|
|
||||||
if (host === '127.0.0.1' || host === 'localhost') {
|
|
||||||
connectFunctionsEmulator(functions, host, 5001);
|
|
||||||
}
|
|
||||||
const secureFunction = httpsCallable(functions, 'securefunction')
|
|
||||||
secureFunction().then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
</style>
|
|
@ -11,6 +11,7 @@
|
|||||||
<input @click="signup" type="submit" name="" value="Sign Up">
|
<input @click="signup" type="submit" name="" value="Sign Up">
|
||||||
<a><router-link to="/login">Already have an account?</router-link></a>
|
<a><router-link to="/login">Already have an account?</router-link></a>
|
||||||
</div>
|
</div>
|
||||||
|
<p v-if="displayFirebaseError">{{ FirebaseError }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -25,7 +26,9 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: "",
|
email: "",
|
||||||
password: ""
|
password: "",
|
||||||
|
displayFirebaseError: false,
|
||||||
|
FirebaseError: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -35,17 +38,16 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
signup() {
|
signup() {
|
||||||
|
this.displayFirebaseError = false;
|
||||||
const auth = getAuth(app)
|
const auth = getAuth(app)
|
||||||
createUserWithEmailAndPassword(auth, this.email, this.password)
|
createUserWithEmailAndPassword(auth, this.email, this.password)
|
||||||
.then((userCredential) => {
|
.then((userCredential) => {
|
||||||
const user = userCredential.user
|
const user = userCredential.user
|
||||||
this.$router.push({path:'/secure'})
|
this.$router.push({path:'/account'})
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
const errorCode = error.code
|
this.FirebaseError = error.message
|
||||||
const errorMessage = error.message
|
this.displayFirebaseError = true
|
||||||
console.log(errorCode)
|
|
||||||
console.log(errorMessage)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ function loadPage(component) {
|
|||||||
export default [
|
export default [
|
||||||
{path: "/", component:loadPage("MapPage")},
|
{path: "/", component:loadPage("MapPage")},
|
||||||
{path: "/insights", component:loadPage("InsightsPage")},
|
{path: "/insights", component:loadPage("InsightsPage")},
|
||||||
{path: "/secure", component:loadPage('SecurePage'), beforeEnter: isAuth},
|
{path: "/account", component:loadPage('AccountPage'), beforeEnter: isAuth},
|
||||||
{path: "/signup", component:loadPage('SignUpPage')},
|
{path: "/signup", component:loadPage('SignUpPage')},
|
||||||
{path: "/login", component:loadPage('LoginPage')},
|
{path: "/login", component:loadPage('LoginPage')},
|
||||||
]
|
]
|
Reference in New Issue
Block a user