Firestore Data Modeling
Firestore Data Modeling
RideEase uses Google Cloud Firestore as its primary NoSQL database to store user profiles and manage role-based access. The database structure is designed for low-latency lookups during the authentication and onboarding flows.
Collection: users
All user-related data is stored within a top-level users collection. Each document within this collection is indexed by the user's unique Firebase Authentication ID (UID).
Document Schema
| Field | Type | Description |
| :--- | :--- | :--- |
| userId | String | The unique identifier provided by Firebase Auth. |
| email | String | The user's registered email address. |
| fullName | String | The user's legal or preferred name. |
| phoneNumber | String | The verified phone number (e.g., +91 9876543210). |
| userType | String | Defines the user role: rider or driver. |
| profilePictureUrl| String | URL path to the user's hosted profile image. |
| isPhoneVerified | Boolean | Flag indicating if the user has completed OTP verification. |
| detailsSubmitted | Boolean | Flag used to determine if the user should proceed to the main dashboard or the profile completion screen. |
Data Representation
In the Android application, this structure is represented by the User model. When fetching data from Firestore, the document fields map directly to the object properties.
// Example Firestore Document Structure (users/{uid})
{
"userId": "uA7b8C9d0E1fG2h3I4j5K",
"email": "user@example.com",
"fullName": "Vikash Kumar Singh",
"phoneNumber": "+91 9988776655",
"userType": "rider",
"profilePictureUrl": "https://firebasestorage...",
"isPhoneVerified": true,
"detailsSubmitted": true
}
Key Operations
1. Initial User Provisioning
When a user signs up via AuthViewModel, a skeleton document is created. This ensures the user is registered in the database even before they complete their full profile.
// Logic used by AuthViewModel to initialize a user
Map<String, Object> userData = new HashMap<>();
userData.put("userId", uid);
userData.put("email", email);
userData.put("userType", userType);
userData.put("detailsSubmitted", false);
// Set with MergeOptions to avoid overwriting existing data
firestore.collection("users").document(uid).set(userData, SetOptions.merge());
2. Profile Completion
During the UserDetailsActivity flow, the app updates the existing document with personal information and sets the detailsSubmitted flag to true. This transition is critical for the app's navigation logic (managed by AuthUtils), which directs users to either the MainActivity or the onboarding profile screen based on this boolean.
3. Role Validation
The userType field is used during the login process to ensure users are logging into the correct interface. If a user registered as a "Driver" attempts to log in through the "Rider" portal, the AuthViewModel validates this field against the Firestore document and prevents unauthorized access.
Security Rules Recommendations
To protect user data, the following security logic is applied:
- Read: Users can only read their own document where
request.auth.uid == userId. - Write: Users can only write to their own document.
- Validation: The
userTypemust be eitherriderordriver.