The Problem That Pushed Me to Build This
A client came to us at Helion 360 with a frustrating but common situation. Their operations team was generating weekly Excel reports — sales summaries, campaign performance data, regional breakdowns — and distributing them manually via email. Different stakeholders needed different slices of data, and the whole process was error-prone, slow, and completely unsecured. Reports were forwarded, printed, shared with people who shouldn't have access, and sometimes just lost.
They needed a centralized, permission-aware system where the right people could access the right reports — and nobody else could. Firebase turned out to be the right backbone for this. Here's exactly how I built it.
Why Firebase Made Sense Here
Before jumping into the build, let me explain the architectural choice. Firebase gives you three things that made this project viable without a heavy backend:
- Firebase Authentication — handles user identity cleanly
- Cloud Firestore — stores metadata and access control rules
- Firebase Storage — hosts the actual Excel files securely
The combination lets you enforce access at the storage and database level using Firebase Security Rules, which means even if someone discovers a file path, they can't download it without the right credentials and role assignment. That was the core requirement for this client.
Step 1: Setting Up the Firebase Project
I started by creating a new Firebase project and enabling Authentication with email/password as the primary sign-in method. For this client, users were internal staff, so there was no need for social login.
Next, I set up Firestore with a users collection. Each document used the Firebase Auth UID as the document ID and stored a role field — values like admin, regional_manager, and viewer. This became the foundation of the access control logic.
The Firestore structure for reports looked like this:
- /reports/{reportId} — stores metadata: title, upload date, file path in Storage, and an
allowedRolesarray - /users/{uid} — stores the user profile including their assigned role
Step 2: Uploading Excel Files to Firebase Storage
Rather than converting the Excel files to another format, I kept them as .xlsx files. The client's stakeholders were already comfortable opening Excel, and maintaining the format preserved all formulas and formatting.
I built a simple admin upload interface using React. When an admin uploads a file, the app does three things in sequence:
- Uploads the
.xlsxfile to Firebase Storage under a structured path:reports/{year}/{month}/{filename}.xlsx - Gets the storage reference path (not a public URL — important distinction)
- Creates a Firestore document in
/reportswith the metadata and theallowedRolesarray the admin selects during upload
I deliberately avoided using public download URLs. Instead, the app generates signed URLs on demand — temporary, expiring links that are only created after the user's role has been verified server-side.
Step 3: Writing Security Rules That Actually Work
This is where most implementations fall apart. Firebase Security Rules are powerful but easy to get wrong. Here's the approach I used for Storage:
The rule checks that the requesting user is authenticated, then reads their Firestore user document to get their role, then verifies that the report's allowedRoles array contains that role. If any step fails, access is denied at the infrastructure level — not just the UI level.
For Firestore, I wrote rules that prevent users from reading report documents unless their role matches the allowedRoles field. This means even the list of available reports is filtered — a regional manager in the Northeast doesn't see reports tagged only for the West Coast team.
Step 4: Building the User-Facing Report Dashboard
The front-end is a clean dashboard that shows only the reports a logged-in user has permission to see. When a user authenticates, the app fetches their role from Firestore, then queries the /reports collection using a array-contains filter on allowedRoles.
Each report card shows the title, upload date, and a download button. When the user clicks download, a Firebase Cloud Function is triggered. The function:
- Verifies the user's token server-side
- Confirms the user's role against the report's
allowedRoles - Generates a signed URL with a 15-minute expiry
- Returns that URL to the client for the download
The 15-minute expiry means even if someone screenshots the URL or shares it, it becomes useless almost immediately. This was a specific requirement from the client's compliance team.
Step 5: Admin Controls and Audit Logging
The admin interface lets authorized users upload new reports, assign roles to each report, and manage user role assignments. But I also added something the client hadn't initially asked for: audit logging.
Every time a signed URL is generated — meaning every time someone downloads a report — the Cloud Function writes a log entry to a Firestore /audit_logs collection with the user UID, report ID, timestamp, and IP address. The admin can view this log in a simple table view.
This turned out to be one of the most-praised features. The operations lead told me within the first month that they'd already used it to catch a situation where an employee was downloading reports outside of business hours — something that would have been completely invisible in the old email system.
What I'd Do Differently Next Time
A few honest lessons from this build:
- Role management gets complex fast. If I were starting over, I'd implement a more granular permissions model from day one rather than simple role strings — something like attribute-based access control.
- Signed URL generation adds latency. The Cloud Function call before each download adds about 800ms–1.2s. For this client it's acceptable, but for a high-volume use case I'd cache the logic or use a different architecture.
- Test your Security Rules exhaustively. Firebase's Rules Playground is helpful but not comprehensive. I now always write automated tests against rules using the Firebase Emulator Suite before deploying.
The Outcome
The system has been running for several months. The client eliminated manual email distribution entirely, reduced report-related support requests by roughly 70%, and now has a full audit trail for compliance purposes. The Excel files themselves required zero modification — stakeholders download them and open them exactly as they always did, just through a controlled, secure channel.
If your business is still distributing sensitive reports via email or shared drives, this kind of architecture is worth considering. Firebase makes it achievable without a large backend team, and the security model is genuinely robust when the rules are written carefully.


