Firebase + Vue Track Users Location Real-Time On The Google Maps
Tags: firebase, vue, programming
Published: 2021-05-03 13:35:20

{% youtube CgGHqI7P0yU %}

By the end of this tutorial, you’ll be able to:

- Track individual driver’s location, with their permission, using HTML5 Geolocation API after logging into the app.
- Store authenticated driver’s location data to the Cloud Firestore as the location changes.
- Show all of the active driver’s current location in real-time on Google Maps in the Admin view.

>🛑 *The app will only get location updates as long as it’s in the foreground state and it STOPS giving updates when it’s in the background mode.*

###What You’ll Make By The End Of This Tutorial

![alt text](https://softauthor.com/wp-content/uploads/2020/04/Vuejs-Firebase-Track-Multiple-Users-Realtime.gif)

###Infographics

![alt text](https://softauthor.com/wp-content/uploads/2020/04/Vuejs-Firebase-Track-Multiple-Users-Realtime.jpg)

###Table Of Contents

- [Create A New Firebase User](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#new-firebase-user)
- [Add User Roles](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#add-user-roles)
- [Firebase Security Rules](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#security-rules)
- [Sign In A User](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#sign-in-firebase-user)
- [Navigation Auth Guards](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#navigation-auth-guards)
- [Driver View](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#driver-view)
- [Get User Location Using watchPosition()](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#get-user-locatoin-using-watch-position)
- [Show Current Location On The Map](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#show-location-on-the-google-map)
- [Stop Location Updates](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#stop-location-updates)
- [Add Location Data To The Cloud Firestore](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#add-location-data-to-cloud-firestore)
- [Mock Multiple Driver’s Movement on the iOS Simulator](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#mock-multiple-drivers-movement-ios-simulator)
- [Admin View: Show Map, Markers and InfoWindows](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/#admin-view-get-all-drivers)

###Project Setup
{% youtube 3A57dcz8A8E %}

I have created five page based components in the [starter Vue project](https://softauthor.com/getting-started-with-vue-js/) which are:

- Login.vue
- Signup.vue
- Driver.vue
- Admin.vue

Before going further, we need to include a couple of files in index.html.

Add a Semantic UI CSS framework to build a UI.

```HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
```

Also, add the Google Maps JavaScript library CDN link to the project.

```HTML
<script src="https://maps.googleapis.com/maps/api/js?key=[YOUR_API_KEY]">
```

{% youtube ASiEw-eakWM %}

###Create A New Firebase User

Of course, we need authentication in place to track multiple drivers at once.

Firebase offers a variety of sign-in methods such as [Facebook](https://softauthor.com/firebaseui-vue-facebook-google-auth/#sign-in-with-facebook-using-firebaseui), [Google](https://softauthor.com/firebaseui-vue-facebook-google-auth/#sign-in-with-google-using-firebaseui), etc but I am going to stick with [Email/Password](https://softauthor.com/firebaseui-vue-facebook-google-auth/#login-with-email-and-password-using-firebaseui) for simplicity sake.

>🛑 *Assuming you already know how to add firebase to the vue.js project.*

{% youtube NpDlC2-Zo0U %}

Enable Email/Password Authentication by going to Firebase Console → Firebase Authentication → Sign-in Method → Email/Password.

Here is the standard signup form with just an email and password.

*Signup.vue*
```HTML
<template>
  <section class="ui centered grid" style="margin-top:30px;">
    <div class="column" style="max-width:450px;">
      <form class="ui segment large form">
        <div class="ui segment">
          <div class="field">
            <div class="ui left icon input large">
              <input type="text" placeholder="Enter your email" v-model="email" />
              <i class="ui icon user"></i>
            </div>
          </div>
          <div class="field">
            <div class="ui left icon input large">
              <input type="password" placeholder="Enter your password" v-model="password" />
              <i class="ui icon key"></i>
            </div>
          </div>
          <button class="ui button fluid large green" @click="signUpButtonPressed">Sign up</button>
        </div>
      </form>
      <router-link :to="{ name: 'Signin' }" tag="a" class="ui button basic">Log in</router-link>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return {
      email: "",
      password: "",
    };
  },
  methods: {
    signUpButtonPressed() {
    },
  }
};
</script>
```
Import firebase at the top inside the script tag.

```JavaScript
import firebase from 'firebase'
```
Then, invoke createUserWithEmailAndPassword() method on the firebase object to create a new user inside the signUpButtonPressed().

```JavaScript
firebase
  .auth()
  .createUserWithEmailAndPassword(this.email, this.password)
  .then(user => {
    console.log("Brand new user is added")
  })
  .catch(error => {
    console.log(error.message);
  });
```
To show all the users' data on the Admin view, add user data to the Cloud Firestore when a new user account is created.

```JavaScript
signUpButtonPressed() {
   firebase
      .auth()
      .createUserWithEmailAndPassword(this.email, this.password)
      .then(user => {
         this.addUserToDB(user);
      })
      .catch(error => {
         this.error = error.message;
      });
},

async addUserToDB({user}) {
   try {
      const db = firebase.firestore();
      _ = await db
         .collection("users")
         .doc(user.uid)
         .set({
            email: user.email,
            active:false
         });
      
   } catch (error) {
      console.log(error.message);
   }
}
```
![alt text](https://softauthor.com/wp-content/uploads/2020/04/users-on-the-cloud-firestore.png)

As you can see, I have created three user accounts from the signup.vue page.

###Add User Roles

- The Admin role will have access to all the drivers stored in the database and will be able to track their location at any time.
- The Driver role will have access to read or write their own data and will be sending location updates to the database as they move.

Adding a role to each user should be done on the server side for security reasons and it can be done in two different ways using Cloud Function.

- [Using Auth Claims](https://softauthor.com/firebase-vuejs-role-based-authentication-authorization/#add-admin-auth-custom-claims).
- Adding read-only (from the client) collection that has user roles on the Cloud Firestore.

For simplicity's sake, I have added three user roles inside the roles collection with the same document ID as the user’s collection.

Two of them have isDriver : true field and one has the isAdmin : true field.

![alt text](https://softauthor.com/wp-content/uploads/2020/04/roles-collection-on-the-cloud-firestore.png)

###Firebase Security Rules

- Only authenticated users can read or write data to the users collection.

```JavaScript
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {	
    match /users/{uid} {
      allow read, write: if request.auth.uid == uid
    }
  }
}
```

- Only authenticated users can read to the roles collection but no one can write to it from the front-end.

```JavaScript
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
   ...	
    match /roles/{uid} {
      allow read: if request.auth.uid == uid;
      allow write: if false;
    }
  }
}
```

- Get all the user data when a signed-in user has an Admin role.

We can access the roles collection inside here using the get method by passing the database path to the isAdmin field.

```JavaScript
 match /users/{uid} {
      allow read, write: if request.auth.uid == uid || get(/databases/$(database)/documents/roles/$(request.auth.uid)).data.isAdmin;
    }
```
>✅ *Want to learn more about Security Rules?*
>[*6 Must-Know Firestore Security Rules*](https://softauthor.com/firebase-cloud-firestore-security-rules/)

[Continue Reading ...](https://softauthor.com/vue-firebase-track-users-location-real-time-on-the-google-maps/)