Skip to main content

Lazy Migration Explained with Code


What is lazy migration?

Lazy migration is a technique used when you want to migrate your database or user accounts gradually. For example, your usernames and passwords are stored in MySQL, but now you are using Firebase for authentication. However, you do not want to lose your existing users. In this case, you can apply lazy migration.

How does it work?

The login page is designed in such a way that it first checks the user's credentials in the old database. If the user is found, the system creates a Firebase account for that user and redirects them to the intended page where they are logged in.

If the user lookup fails, the system shows an error message such as "username or password not available" or may redirect the user to the signup page.

What are the benefits of lazy migration?

  • Existing users can log in seamlessly without facing difficulties.

  • There is no need for users to reset their passwords.

  • New users can directly sign up using the new authentication system.


Backend


import os
import requests
import bcrypt

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

from sqlalchemy.orm import Session

from passlib.context import CryptContext


# ===========================
# Import your database files
# ===========================
from database import SessionLocal
from models import User

# ===========================
# FastAPI App
# ===========================

app = FastAPI(
    title="Authentication API",
    version="1.0.0"
)

# ===========================
# CORS Middleware
# ===========================

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",
        "http://localhost:5173",
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


FIREBASE_API_KEY = "FIREBASE_API_KEY"





class LoginRequest(BaseModel):

    email:str

    password:str





class LoginResponse(BaseModel):

    access_token:str

    token_type:str

    role:str


def hash_password(password: str) -> str:
    return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()

def verify_password(plain_password: str, hashed_password: str) -> bool:
    return bcrypt.checkpw(plain_password.encode(), hashed_password.encode())


def create_firebase_user(email,password):


    signup_url = (
        "https://identitytoolkit.googleapis.com/"
        "v1/accounts:signUp?key="
        + FIREBASE_API_KEY
    )



    response = requests.post(

        signup_url,

        json={

            "email":email,

            "password":password,

            "returnSecureToken":True

        }

    )



    result=response.json()



    # User already migrated

    if (
        "error" in result and
        result["error"]["message"]
        == "EMAIL_EXISTS"
    ):



        login_url=(

        "https://identitytoolkit.googleapis.com/"
        "v1/accounts:signInWithPassword?key="
        + FIREBASE_API_KEY

        )



        response=requests.post(

            login_url,

            json={

                "email":email,

                "password":password,

                "returnSecureToken":True

            }

        )



        result=response.json()




    if "idToken" not in result:


        raise HTTPException(

            status_code=500,

            detail="Firebase login failed"

        )



    return result







@app.post(
    "/loginFirebase",
    response_model=LoginResponse
)
def login(data:LoginRequest):



    db=SessionLocal()



    try:


        # CHANGE THIS IF YOUR COLUMN IS username

        user=db.query(User).filter(

            User.username == data.email

        ).first()



    finally:

        db.close()





    if not user:


        raise HTTPException(

            status_code=400,

            detail="Incorrect email or password"

        )






    # Existing bcrypt check

    if not verify_password(

        data.password,

        user.password

    ):


        raise HTTPException(

            status_code=400,

            detail="Incorrect email or password"

        )






    # Lazy migration to Firebase

    firebase_user=create_firebase_user(

        data.email,

        data.password

    )






    return {


        "access_token":

            firebase_user["idToken"],


        "token_type":

            "bearer",


        "role":

            user.role

    }

Frontend

<div id="login-container" style="font-family: sans-serif; margin:auto auto; max-width: 300px;">
  <h2>Login to Access Premium Content</h2>

  <form id="login-form">

    <div style="margin-bottom: 10px;">
      <label>Email:</label><br />
      <input id="username" placeholder="email@example.com" required
        style="box-sizing: border-box; padding: 8px; width: 100%;"
        type="email" />
    </div>

    <div style="margin-bottom: 10px;">
      <label>Password:</label><br />
      <input id="password" required
        style="box-sizing: border-box; padding: 8px; width: 100%;"
        type="password" />
    </div>

    <div id="error-message" style="color:red; margin-bottom:10px;"></div>

    <button id="login-btn"
      style="background: rgb(0,123,255); color:white; cursor:pointer; padding:10px; width:100%; border:none;"
      type="submit">
      Login
    </button>

  </form>

<script type="module">

const loginForm = document.getElementById("login-form");
const errorDisplay = document.getElementById("error-message");
const loginBtn = document.getElementById("login-btn");

const API_URL = "http://localhost:8000/loginFirebase";

loginForm.addEventListener("submit", async (e)=>{

    e.preventDefault();

    errorDisplay.textContent = "";

    loginBtn.disabled = true;
    loginBtn.textContent = "Checking...";

    const email = document.getElementById("username").value;

    const password = document.getElementById("password").value;

    try {

        const response = await fetch(
            API_URL,
            {
                method:"POST",

                headers:{
                    "Content-Type":"application/json"
                },

                body:JSON.stringify({
                    email:email,
                    password:password
                })
            }
        );

        const data = await response.json();

        if(!response.ok){
            throw new Error(
                data.detail || "Login failed"
            );
        }

        localStorage.setItem(
            "firebase_token",
            data.access_token
        );

        localStorage.setItem(
            "role",
            data.role
        );

        window.location.href =
        "https://www.salimwireless.com";

    }

    catch(error){

        errorDisplay.style.color="red";

        errorDisplay.textContent =
        error.message;

        loginBtn.disabled=false;

        loginBtn.textContent="Login";

    }

});

</script>



Contact Us

Name

Email *

Message *

Popular Posts

Design of CMOS Flip-Flops (SR, D, JK)

Design of CMOS Flip-Flops (SR, D, JK) A flip-flop or latch is a circuit with two stable states, used to store state information. It is the basic storage element in sequential logic and a fundamental building block in digital electronics systems, including computers and communication devices. Flip-flops and latches act as data storage elements for states, pulse counting, and synchronization of variably-timed input signals to a reference clock. Flip-flops can be transparent/opaque (latches) or clocked (synchronous, edge-triggered). Latches are level-sensitive, while flip-flops are edge-sensitive. In sequential logic, the output depends on current inputs and previous states. Fig.1 shows a sequential circuit combining a combinational block and a memory element. ...

Q-function in BER vs SNR Calculation (with Simulation)

Q-function in BER vs. SNR Calculation In digital communications and signal processing, the Q-function plays a significant role in predicting system reliability. It allows engineers to quantify the probability that Gaussian noise will exceed a specific threshold, causing a bit error. What is the Q-function? The Q-function is a mathematical function representing the tail probability of the standard normal (Gaussian) distribution. It is the complementary cumulative distribution function (CCDF) of a standard Gaussian distribution. Q(x) = (1 / √(2Ï€)) ∫â‚“∞ e^(-t² / 2) dt The Role of the Q-function in BER vs. SNR The Q-function is the standard tool for calculating BER in systems like BPSK or QPSK over AWGN (Additive White Gaussian Noise) channels. For BPSK: In BPSK, we transmit +√E b (bit 1) and -√E b (bit 0). The decision boundary is set at 0 . If -√E b was sent, an error occurs if noise r > √...

BER vs SNR for M-ary QAM, M-ary PSK, QPSK, BPSK, ...(MATLAB Code + Simulator)

Bit Error Rate (BER) & SNR Guide Analyze communication system performance with our interactive simulators and MATLAB tools. 📘 Theory 🧮 Simulators 💻 MATLAB Code 📚 Resources BER Definition SNR Formula BER Calculator MATLAB Comparison 📂 Explore M-ary QAM, PSK, and QPSK Topics ▼ 🧮 Constellation Simulator: M-ary QAM 🧮 Constellation Simulator: M-ary PSK 🧮 BER calculation for ASK, FSK, and PSK 🧮 Approaches to BER vs SNR Calculation What is Bit Error Rate (BER)? The BER indicates how many corrupted bits are received compared to the total number of bits sent. It is the primary figur...

Channel Impulse Response (CIR) (with MATLAB + Simulator)

📘 Overview & Theory 📘 How CIR Affects the Signal 🧮 Online Channel Impulse Response Simulator 🧮 MATLAB Codes 📚 Further Reading What is the Channel Impulse Response (CIR)? The Channel Impulse Response (CIR) is a concept primarily used in the field of telecommunications and signal processing. It provides information about how a communication channel responds to an impulse signal. It describes the behavior of a communication channel in response to an impulse signal. In signal processing, an impulse signal has zero amplitude at all other times and amplitude ∞ at time 0 for the signal. Using a Dirac Delta function, we can approximate this. Fig: Dirac Delta Function The result of this calculation is that all frequencies are responded to equally by δ(t) . This is crucial since we never know which frequenci...

FFT Butterfly Method Explained (with Simulations)

4-Point FFT Using Butterfly Method Given: x[n] = {0, 1, 2, 3} Step 1: Split into Even & Odd Even indices: x e = {x[0], x[2]} = {0, 2} Odd indices: x o = {x[1], x[3]} = {1, 3} Step 2: 2-point DFT For any {a, b}: DFT = {a + b, a - b} Even Part (E): {0+2, 0-2} = {2, -2} Odd Part (O): {1+3, 1-3} = {4, -2} Step 3: Combine Using Butterfly X[k] = E[k] + W 4 k O[k] X[k + 2] = E[k] - W 4 k O[k] Twiddle Factors (N=4): W 4 0 = 1, W 4 1 = -j Final Calculations: X[0] = E[0] + W 4 0 O[0] = 2 + (1)(4) = 6 X[2] = E[0] - W 4 0 O[0] = 2 - (1)(4) = -2 X[1] = E[1] + W 4 1 O[1] = -2 + (-j)(-2) = -2 + 2j X[3] = E[1] - W 4 1 O[1] = -2 - (-j)(-2) = -2 - 2j Final Answer: X[k] = {6, -2 + 2j, -2, -2 - 2j} 8-Point FFT Using Butterfly Method Given: x[n] = {0,1,2,3,4,5,6,7} Step 1: Split into Bit-Reversed Order To perform DIT-FFT, split the 8 points into pairs of two: Group A: {x[0], x[4]} = {0, 4}...

Frequency Bands : EHF, SHF, UHF, VHF, HF, MF, LF, VLF and Their Uses

Frequency Bands >> EHF, SHF, UHF, VHF, HF, MF, LF... Frequency Bands and Their Uses 1. Extremely High Frequency (EHF) 30 - 300 GHz Uses 5G Networks 5G millimeter wave band 6G and beyond (Experimental) RADAR 2. Super High Frequency (SHF) 3 - 30 GHz Uses Ultra-wideband (UWB) Airborne RADAR Satellite Communication Microwave Link Communication or SATCOM 3. Ultra High Frequency (UHF) 300 - 3000 MHz Uses Satellite Communication Television Surveillance Navigation aids Also, read important wireless communication terms 4....

Pulse Amplitude Modulation and Demodulation

📘 Overview & Theory of Pulse Amplitude Moduation (PAM) 🧮 Pulse Amplitude Demoduation 🧮 MATLAB Code for PAM 📚 Further Reading 📂 Other Topics on Pulse Amplitude Modulation ... 🧮 Simulation results for comparison of PAM, PWM, PPM, DM, and PCM 🧮 Other Pulse Modulation Techniques (e.g., PWM, PPM, DM, and PCM) 🧮 MATLAB Code for Pulse Amplitude Modulation and Demodulation of an Analog Signal (2) 🧮 MATLAB Code for Pulse Amplitude Modulation and Demodulation of Digital data  Pulse Amplitude Modulation (PAM) Sampling allow us to represent real world continuous signal, such as audio or video, in a format suitable for digital processing and storage. This sampled discrete-time signal is inherently digital. A digital signal is a discrete-time signal that is further quantized in amplitude. Pulse Amplitude modulation (PAM) is the modulation technique in which amplitude of carrier pulses is...

FM Bandwidth and FM Band Explained

FM radio uses the frequency band from 88 MHz to 108 MHz , which is a 20 MHz-wide spectrum . This is the range of carrier frequencies available to stations. 108 MHz − 88 MHz = 20 MHz However, a single FM station occupies only about 200 kHz . This is the bandwidth of the modulated FM signal. 1. Why One FM Station Needs ~200 kHz FM uses frequency modulation . The bandwidth depends on how far the carrier swings. Carson's Rule gives the approximate FM bandwidth: B = 2 ( Δf + f m ) ...