Trevor's Rides
Trevor's Rides is a rideshare app that I am developing using .Net Maui for the Driver and Rider apps and ASP.Net for the server. It's running on the same Google compute engine instance that this very website is running on, which is using Apache as a reverse proxy to serve the sites. If you would like to try out the app for yourself you can follow the steps below. If you would like to take a look under the hood, you can visit the Under the Hood section. If you would like to see future plans for the app, you can visit the Future Plans section.
Android | iOS | Github | Last Update | ||
---|---|---|---|---|---|
Driver App | Rider App | Driver App | Rider App | ||
0.0.1 | 0.0.1 | Coming Soon... | frflcn/TrevorsRides | Jan. 20, 2024 |
Try it Out!
- The first step to trying out the app is to download and install both the rider and driver apps. Make sure that if you are using Android you allow unknown sources to be installed. The iOS version is coming soon.
- Once you've downloaded and installed both apps, create an account for each of the apps. Your accounts should use the same email address, this is necessary for future steps.
- Once you've created both of your accounts, log in to the rider app, and head to the Account page. Here, tap your name, email then phone in that order three times. This should enable the testing feature. Turn the feature on. When this testing feature is turned on it tells the app to request the driver with the same email address as the rider. Otherwise it will just send the ride request to me and you will not be able to see the ride request go through.
- Once you've enabled and turned on the testing feature, feel free to explore the app. When you request a ride, do not use your actual credit card information as it will not go through. Use one of Stripe's test cards for all payments. One such card number is 4242 4242 4242 4242 with any future expiration date, a three digit CVC number, and any Name and Zip code.
Under the Hood
As I've stated before the rider and driver apps are programmed using .Net Maui and the server using ASP.Net. The apps communicate with the server via websockets and https requests, and the server uses an SQLite database to persist the state of the app.
The Database
The server utilizes an SQLite database to persist any data that is necessary to maintain across server restarts, such as Login information and ride information. Information such as driver location and whether or not they are online is kept in memory. The Database has six tables: Driver Accounts, Rider Accounts, Driver Account Setup, Rider Account Setup, Rides in Progress and Completed Rides. The tables correlating to rider and driver accounts are very similiar in structure but are kept separate for obvious reasons. The account setup tables exist solely to persist information needed to verify your email account. The Rides In Progress table is very similiar to the Completed Rides but is also kept separate. These tables include the driver ID, the rider ID, trip ID, trip Status, the pickup, dropoff and stops locations; and there are future plans to utilize the path that the trip has taken, as well as any updates to the trip plan.
Logging In
Logging in consists of sending an https Get request to the server with the Username and Password in the headers. The password is store in the database as a BCrypt hash. Your password is peppered by me then salted by BCrypt then hashed with a workload that takes my server 100 ms to complete. Your password is safe from offline attacks, unless an attacker manages to find the pepper and you used an easily predictable password. Once logged in the server returns an AccountSession object which contains information about your account and a Session Token. The session token is used to authenticate subsequent requests and expires 24 hours after it is issued. Upon reopening the app, the app will use the session token if it has not exprired to auto log you in, at which point the server will send a fresh session token.
Making a Ride Request
As a rider enters in place information for the pickup or dropoff location, the app is sending that information to Google Places Autocomplete api which populates the suggestions list. When the user taps on a suggestion it sends that back off to Google Places Details which sends back a lat and long, the address and name of the place. When the rider has selected both a pickup and dropoff it sends the lat and long to Google Routes which sends back route. The route includes trip duration and trip length which is used to calculate the trip cost as well as a polyline to show on the map. When the rider clicks book a ride it sends the pickup and dropoff location to my server, which calculates the ride price with another Google Route request, creates Checkout Session from Stripe and sends the Checkout Session's url to back to the rider. When the rider completes the Checkout Session, Stripe processes the payment and sends a Webhook to my server at which point I send a ride request to the respective driver through a websocket message that the driver has already setup by logging in. The driver then accepts or declines the request which sends a websocket message back to my server which I am listening for using a TaskCompletionSource and handle it appropriately. The are future plans to be able to complete, cancel or update the ride plan, but for now this will do.
Technology Used
- .Net Maui
- ASP.Net
- Entity Framework
- SQLite
- WebSockets
- Linux
- Google Cloud Compute Engine
- Google Routes
- Google Places
- Stripe
- Apache
- BCrypt
Future Plans
- Actually be able to complete or cancel the trip
- Be able to update the ride plan
- Record driver and rider locations as the trip is in progress for safety and trip authentication
- In the Rider Account, store an encrypted Customer Object to send to Stripe to persist credit card information across checkout sessions. The customer object shall be able to be decrypted via an encrypted key stored in the database which is able to be decrypted by one hash less than the hashed password stored in the database; so that when the rider logs in, the password is hashed to find the key to the encrypted key which is sent to the Rider in the Account Session object. The password is hashed one more time to verify the log in. The key sent to the rider is used to decrypt the Customer Object when needed. The two step decryption process from password to encrypted key to encrypted data is done so that during a password change only the encrypted key needs to be reencrypted and not all of the encrypted user data which could be large in the future.
- Access ride history in the driver and rider apps
- Deny the ability to make a ride request when no drivers are signed on
- Implement Payment Intents so that the customer can be charged after the ride completes to account for things such as the ride plan updating, and unpredictable fees(fees for things such as waiting for the rider, messes and returned items)
- Implement an admin page for myself to do admin things such as viewing who's online and the rides in progress, as well as turning off new ride requests so that the server can be shutdown or restarted gracefully without interfering with ongoing rides.
- Give the user the ability to update their user accounts