Firebase Users CSV Exporter

Export all Firebase Authentication users to CSV with Identifier, Created, and Signed In columns

Size

8.5 KB

Version

1.0.1

Created

Apr 1, 2026

Updated

15 days ago

1// ==UserScript==
2// @name		Firebase Users CSV Exporter
3// @description		Export all Firebase Authentication users to CSV with Identifier, Created, and Signed In columns
4// @version		1.0.1
5// @match		https://*.console.firebase.google.com/*
6// @icon		https://www.gstatic.com/mobilesdk/240501_mobilesdk/firebase_16dp.png
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Firebase Users CSV Exporter: Extension loaded');
12
13    // Debounce function to prevent multiple rapid calls
14    function debounce(func, wait) {
15        let timeout;
16        return function executedFunction(...args) {
17            const later = () => {
18                clearTimeout(timeout);
19                func(...args);
20            };
21            clearTimeout(timeout);
22            timeout = setTimeout(later, wait);
23        };
24    }
25
26    // Function to convert data to CSV format
27    function convertToCSV(data) {
28        if (!data || data.length === 0) {
29            return 'Identifier,Created,Signed In\n';
30        }
31
32        const headers = ['Identifier', 'Created', 'Signed In'];
33        const csvRows = [headers.join(',')];
34
35        data.forEach(row => {
36            const values = [
37                `"${(row.identifier || '').replace(/"/g, '""')}"`,
38                `"${(row.created || '').replace(/"/g, '""')}"`,
39                `"${(row.signedIn || '').replace(/"/g, '""')}"`
40            ];
41            csvRows.push(values.join(','));
42        });
43
44        return csvRows.join('\n');
45    }
46
47    // Function to download CSV file
48    function downloadCSV(csvContent, filename) {
49        const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
50        const link = document.createElement('a');
51        const url = URL.createObjectURL(blob);
52        
53        link.setAttribute('href', url);
54        link.setAttribute('download', filename);
55        link.style.visibility = 'hidden';
56        document.body.appendChild(link);
57        link.click();
58        document.body.removeChild(link);
59        
60        console.log('Firebase Users CSV Exporter: CSV file downloaded successfully');
61    }
62
63    // Function to extract user data from the table
64    function extractUserData() {
65        console.log('Firebase Users CSV Exporter: Extracting user data from table');
66        
67        const userData = [];
68        const tableRows = document.querySelectorAll('table[role="grid"][aria-label*="Usuario"] tbody.mdc-data-table__content tr.mat-mdc-row');
69        
70        console.log(`Firebase Users CSV Exporter: Found ${tableRows.length} user rows`);
71
72        tableRows.forEach((row, index) => {
73            try {
74                // Extract identifier (email or phone)
75                const identifierCell = row.querySelector('td.cdk-column-identifier .identifier-text');
76                const identifier = identifierCell ? identifierCell.textContent.trim() : '';
77
78                // Extract created date
79                const createdCell = row.querySelector('td.cdk-column-created-at');
80                const created = createdCell ? createdCell.textContent.trim() : '';
81
82                // Extract last login date
83                const lastLoginCell = row.querySelector('td.cdk-column-last-login');
84                const signedIn = lastLoginCell ? lastLoginCell.textContent.trim() : '';
85
86                if (identifier) {
87                    userData.push({
88                        identifier: identifier,
89                        created: created,
90                        signedIn: signedIn
91                    });
92                    console.log(`Firebase Users CSV Exporter: Extracted user ${index + 1}: ${identifier}`);
93                }
94            } catch (error) {
95                console.error(`Firebase Users CSV Exporter: Error extracting row ${index}:`, error);
96            }
97        });
98
99        return userData;
100    }
101
102    // Function to handle export button click
103    async function handleExportClick() {
104        console.log('Firebase Users CSV Exporter: Export button clicked');
105        
106        const button = document.querySelector('button[data-export-users-csv]');
107        if (!button) return;
108
109        // Disable button and show loading state
110        button.disabled = true;
111        const originalText = button.querySelector('.mdc-button__label').textContent;
112        button.querySelector('.mdc-button__label').textContent = 'Exportando...';
113
114        try {
115            // Extract user data
116            const userData = extractUserData();
117            
118            if (userData.length === 0) {
119                alert('No se encontraron usuarios para exportar. Asegúrate de que la tabla de usuarios esté visible.');
120                console.log('Firebase Users CSV Exporter: No users found to export');
121                return;
122            }
123
124            // Convert to CSV
125            const csvContent = convertToCSV(userData);
126            
127            // Generate filename with timestamp
128            const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
129            const filename = `firebase-users-${timestamp}.csv`;
130            
131            // Download CSV
132            downloadCSV(csvContent, filename);
133            
134            console.log(`Firebase Users CSV Exporter: Successfully exported ${userData.length} users`);
135            
136        } catch (error) {
137            console.error('Firebase Users CSV Exporter: Error during export:', error);
138            alert('Error al exportar usuarios. Por favor, intenta de nuevo.');
139        } finally {
140            // Re-enable button
141            button.disabled = false;
142            button.querySelector('.mdc-button__label').textContent = originalText;
143        }
144    }
145
146    // Function to create and add the export button
147    function addExportButton() {
148        // Check if button already exists
149        if (document.querySelector('button[data-export-users-csv]')) {
150            console.log('Firebase Users CSV Exporter: Export button already exists');
151            return;
152        }
153
154        // Find the "Agregar usuario" button
155        const addUserButton = document.querySelector('button[data-test-id="add-user-button"]');
156        
157        if (!addUserButton) {
158            console.log('Firebase Users CSV Exporter: Add user button not found, will retry');
159            return;
160        }
161
162        console.log('Firebase Users CSV Exporter: Adding export button');
163
164        // Create the export button with matching Firebase style
165        const exportButton = document.createElement('button');
166        exportButton.setAttribute('data-export-users-csv', 'true');
167        exportButton.className = 'mdc-button mat-mdc-button-base mdc-button--raised mat-mdc-raised-button mat-primary';
168        exportButton.style.marginLeft = '8px';
169        
170        exportButton.innerHTML = `
171            <span class="mat-mdc-button-persistent-ripple mdc-button__ripple"></span>
172            <span class="mdc-button__label">Exportar CSV</span>
173            <span class="mat-focus-indicator"></span>
174            <span class="mat-mdc-button-touch-target"></span>
175        `;
176
177        // Add click event listener
178        exportButton.addEventListener('click', handleExportClick);
179
180        // Insert the button next to "Agregar usuario" button
181        const parentContainer = addUserButton.parentElement;
182        if (parentContainer) {
183            parentContainer.insertBefore(exportButton, addUserButton.nextSibling);
184            console.log('Firebase Users CSV Exporter: Export button added successfully');
185        }
186    }
187
188    // Function to initialize the extension
189    function init() {
190        console.log('Firebase Users CSV Exporter: Initializing extension');
191        
192        // Check if we're on the users page
193        if (!window.location.href.includes('/authentication/users')) {
194            console.log('Firebase Users CSV Exporter: Not on users page, waiting for navigation');
195        }
196
197        // Add the export button
198        addExportButton();
199
200        // Observe DOM changes to handle dynamic content loading
201        const observer = new MutationObserver(debounce(() => {
202            if (window.location.href.includes('/authentication/users')) {
203                addExportButton();
204            }
205        }, 500));
206
207        // Start observing
208        observer.observe(document.body, {
209            childList: true,
210            subtree: true
211        });
212
213        console.log('Firebase Users CSV Exporter: Extension initialized successfully');
214    }
215
216    // Wait for the page to be fully loaded
217    if (document.readyState === 'loading') {
218        document.addEventListener('DOMContentLoaded', init);
219    } else {
220        // DOM is already ready
221        setTimeout(init, 1000);
222    }
223
224})();
Firebase Users CSV Exporter | Robomonkey