Skip to main content

Overview

The users collection stores user profile information, roles, and preferences. Each document is keyed by the Firebase Auth UID.

Collection Path

users/{userId}

Document Schema

User Document
object

Example Document

{
  "email": "[email protected]",
  "displayName": "Juan Pérez",
  "photoURL": "https://lh3.googleusercontent.com/...",
  
  "role": "customer",
  "permissions": [],
  
  "phone": "3001234567",
  "document": "1234567890",
  
  "addresses": [
    {
      "label": "Casa",
      "address": "Calle 123 #45-67 Apto 301",
      "city": "Bogotá",
      "department": "Cundinamarca",
      "isDefault": true
    },
    {
      "label": "Oficina",
      "address": "Carrera 7 #32-16 Piso 5",
      "city": "Bogotá",
      "department": "Cundinamarca",
      "isDefault": false
    }
  ],
  
  "createdAt": "2026-01-15T10:00:00Z",
  "lastLogin": "2026-03-05T09:30:00Z",
  
  "emailNotifications": true,
  "whatsappNotifications": false
}

Queries

Get User by ID

const userDoc = await db.collection('users').doc(userId).get();
const userData = userDoc.data();

Get All Admins

const snapshot = await db.collection('users')
    .where('role', '==', 'admin')
    .get();

Search Users by Email

const snapshot = await db.collection('users')
    .where('email', '>=', searchTerm)
    .where('email', '<=', searchTerm + '\uf8ff')
    .get();

Role-Based Access

Customer Role

Default role for all new users:
  • Can view own orders
  • Can update own profile
  • Can create orders via checkout

Admin Role

Full platform access:
  • Can view/edit all orders
  • Can manage products
  • Can access treasury/reports
  • Can manage users

Staff Role (Optional)

Limited admin access:
  • Can view orders
  • Can update order status
  • Cannot manage products or users

User Creation Flow

When a user signs up via Firebase Auth:
// In auth-logic.js or Cloud Function
await db.collection('users').doc(user.uid).set({
    email: user.email,
    displayName: user.displayName || '',
    photoURL: user.photoURL || '',
    role: 'customer',
    createdAt: admin.firestore.FieldValue.serverTimestamp(),
    lastLogin: admin.firestore.FieldValue.serverTimestamp(),
    emailNotifications: true
});

Checking Admin Status

From global-components.js:646-656:
onAuthStateChanged(auth, async (user) => {
    if (user) {
        // Check cached role
        let role = sessionStorage.getItem('pixeltech_user_role');
        
        if (!role) {
            const userSnap = await getDoc(doc(db, "users", user.uid));
            role = (userSnap.exists() && userSnap.data().role === 'admin') 
                ? 'admin' 
                : 'customer';
            sessionStorage.setItem('pixeltech_user_role', role);
        }
        
        const isAdmin = role === 'admin';
        const link = isAdmin ? '/admin/index.html' : '/profile.html';
        // Update UI...
    }
});

Security Rules

Recommended Firestore security rules:
match /users/{userId} {
  // Users can read their own profile
  allow read: if request.auth != null && request.auth.uid == userId;
  
  // Users can update their own profile (except role)
  allow update: if request.auth != null && 
                request.auth.uid == userId &&
                request.resource.data.role == resource.data.role;
  
  // Admins can read/write all users
  allow read, write: if request.auth != null &&
                      get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
  
  // User creation via Cloud Functions or Auth triggers only
  allow create: if false;
}

Indexes

Required indexes:
// Role-based queries
users: [role ASC]

// Email search
users: [email ASC]

// Recent users
users: [createdAt DESC]

Profile Management

Update Profile

await db.collection('users').doc(userId).update({
    displayName: newName,
    phone: newPhone,
    document: newDocument
});

Add Address

await db.collection('users').doc(userId).update({
    addresses: admin.firestore.FieldValue.arrayUnion({
        label: 'Nueva Dirección',
        address: 'Calle 456 #78-90',
        city: 'Medellín',
        department: 'Antioquia',
        isDefault: false
    })
});

Set Default Address

const userDoc = await db.collection('users').doc(userId).get();
const addresses = userDoc.data().addresses || [];

const updated = addresses.map((addr, idx) => ({
    ...addr,
    isDefault: idx === targetIndex
}));

await db.collection('users').doc(userId).update({ addresses: updated });

Build docs developers (and LLMs) love