Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the twentytwenty domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in C:\inetpub\wwwroot\blogs\wp-includes\functions.php on line 6121
Akshit – Club TechKnowHow!
Categories
Firebase Odoo

Seamless User Management: Integrating Firebase Authentication with Odoo

Introduction

In this article, we’ll explore how to integrate Firebase Authentication with Odoo ERP, creating a seamless connection between user management in Firebase and partner management in Odoo. This integration allows you to store Firebase UIDs in the Odoo model and link user actions between both systems.

Prerequisites: 

  • Node.js and npm installed
  • Firebase Project setup
  • Odoo running instance

Step 1: Setting up the project 

npm init -y
npm install express firebase dotenv xmlrpc

Step 2: Setup Firebase Configuration

Create a firebaseConfig.js file to initialize the Firebase client SDK

import { initializeApp as initializeClientApp } from "firebase/app"; 
import dotenv from 'dotenv';  

dotenv.config(); 
const firebaseConfig = {
  apiKey: process.env.API_KEY,
  authDomain: process.env.AUTH_DOMAIN,
  projectId: process.env.PROJECT_ID,
  storageBucket: process.env.STORAGE_BUCKET,
  messagingSenderId: process.env.MESSAGING_SENDER_ID,
  appId: process.env.APP_ID,
  measurementId: process.env.MEASUREMENT_ID
 };
  const firebaseClientApp = initializeClientApp(firebaseConfig);
  export default firebaseClientApp;

Step 3: Odoo Configuration

Create an odooConfig.js file to configure odoo connection

import dotenv from 'dotenv';
import xmlrpc from 'xmlrpc';

dotenv.config();

const ODOO_URL = process.env.ODOO_URL;
const ODOO_DB = process.env.ODOO_DB;
const ODOO_USERNAME = process.env.ODOO_USERNAME;
const ODOO_PASSWORD = process.env.ODOO_PASSWORD;
async function getOdooConnection() {
return new Promise((resolve, reject) => {
const common = xmlrpc.createClient({ url: `${ODOO_URL}/xmlrpc/2/common` });
   common.methodCall('authenticate', [ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD, {}], (err, uid) => {
if (err || !uid) {
return reject('Authentication failed');
}
console.log(`Authenticated with UID: ${uid}`);
const models = xmlrpc.createClient({ url: `${ODOO_URL}/xmlrpc/2/object` });
resolve({ models, uid });
});
  });
}
export { ODOO_URL, ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD, getOdooConnection };

Step 4: Creating Authentication Routes

Create a authRoute.js file to handle signup, signin, and signout operations

import express from 'express';
import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut } from 'firebase/auth';
import firebaseClientApp from './firebaseConfig.js';
import { getOdooConnection, ODOO_DB, ODOO_PASSWORD } from './odooConfig.js';


const clientAuth = getAuth(firebaseClientApp);
const router = express.Router();


router.post('/signup', async (req, res) => {
    const { email, password } = req.body;
    try {
        const { models, uid } = await getOdooConnection();


        // Create user in Firebase
        const userCredential = await createUserWithEmailAndPassword(clientAuth, email, password);
        const firebaseUid = userCredential.user.uid;


        // Check if user already exists in Odoo
        const existingPartnerId = await new Promise((resolve, reject) => {
            models.methodCall('execute_kw', [ODOO_DB, uid, ODOO_PASSWORD, 'res.partner', 'search', [[['x_firebase_uid', '=', firebaseUid]]]], (error, result) => {
                if (error) {
                    reject(error);
                } else {
                    resolve(result[0]);
                }
            });
        });


        let odooPartnerId = existingPartnerId;
        if (!existingPartnerId) {
            // Create new partner in Odoo
            odooPartnerId = await new Promise((resolve, reject) => {
                models.methodCall('execute_kw', [ODOO_DB, uid, ODOO_PASSWORD, 'res.partner', 'create', [{
                    'name': email,
                    'email': email,
                    'x_firebase_uid': firebaseUid
                }]], (error, result) => {
                    if (error) {
                        reject(error);
                    } else {
                        resolve(result);
                    }
                });
            });
        }


        res.status(200).json({ message: 'User signed up successfully', uid: firebaseUid, odooPartnerId });
    } catch (error) {
        console.error('Error during signup:', error);
        res.status(500).json({ message: 'Failed to sign up user' });
    }
});


router.post('/signin', async (req, res) => {
    const { email, password } = req.body;
    try {
        const userCredential = await signInWithEmailAndPassword(clientAuth, email, password);
        const firebaseUid = userCredential.user.uid;


        const { models, uid } = await getOdooConnection();


        // Find corresponding partner in Odoo
        const partnerId = await new Promise((resolve, reject) => {
            models.methodCall('execute_kw', [ODOO_DB, uid, ODOO_PASSWORD, 'res.partner', 'search', [[['x_firebase_uid', '=', firebaseUid]]]], (error, result) => {
                if (error) {
                    reject(error);
                } else {
                    resolve(result[0]);
                }
            });
        });


        if (!partnerId) {
            throw new Error('No corresponding partner found in Odoo');
        }


        res.status(200).send({ status: 'success', user: userCredential.user, partnerId });
    } catch (error) {
        res.status(400).send({ status: 'error', message: error.message });
    }
});


router.post('/signout', async (req, res) => {
    try {
        await signOut(clientAuth);
        res.status(200).send({ status: 'success', message: 'User signed out successfully' });
    } catch (error) {
        res.status(400).send({ status: 'error', message: error.message });
    }
});


export default router;

Step 5: Setting Up Odoo

  1. Log in to your Odoo instance as an administrator.
  2. Go to Settings > Technical > Database Structure > Models.
  3. Find the “res.partner” model and add a new field:
    • Field Name: x_firebase_uid
    • Field Label: Firebase UID
    • Field Type: Char

This will allow us to store the Firebase UID for each user in Odoo.

Step 6: Create the main server

Create a server.js file to setup your express application

Copyimport express from 'express';
import authRoutes from './authRoutes.js';


const app = express();
app.use(express.json());


app.use('/auth', authRoutes);


const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Step 7: Environment Variables

Create a .env file in your project root to store sensitive information:

API_KEY=your_firebase_api_key
AUTH_DOMAIN=your_firebase_auth_domain
PROJECT_ID=your_firebase_project_id
STORAGE_BUCKET=your_firebase_storage_bucket
MESSAGING_SENDER_ID=your_firebase_messaging_sender_id
APP_ID=your_firebase_app_id
MEASUREMENT_ID=your_firebase_measurement_id

ODOO_URL=your_odoo_url
ODOO_DB=your_odoo_database_name
ODOO_USERNAME=your_odoo_username
ODOO_PASSWORD=your_odoo_password

By following these steps, you’ve successfully integrated Firebase Authentication with Odoo ERP. This seamless connection enables you to manage users in Firebase while maintaining partner data in Odoo. Future improvements could include extending this integration to other Firebase services or adding additional functionality in Odoo based on user actions.

Something not working?
Ensure that your environment variables are correctly configured and that the Odoo instance is properly connected. Check Firebase project permissions and Odoo server logs for detailed error information.

Still not working?
Comment below and i’ll make sure I get back to you!

 

Categories
Data Structures & Algorithms Java

Dynamic Connectivity Problem

What is Dynamic Connectivity?

In computing and graph, a dynamic connectivity structure is a data structure that dynamically maintains information about the connected components of graph.

Dynamic Connectivity Problem

Given a set of N objects.

  • Union command: connect two objects.
  • Find/connected query: is there a path connecting the two objects?

Q. Is there a path connecting p and q?

Source: Algorithm by Robert Sedgewick

 

 

 

 

 

 

 

Union Find Data Type

The goal is to design an efficient data structure for union-find with two commands, union and connected. It can be implemented by two different algorithms, Quick Find and Quick Union.

Quick Find

This quick find algorithm is called eager algorithm to solve dynamic connectivity problem. The data structure includes an Integer array id[] of length N and we consider p and q  to be connected iff they have the same id.

for (int i = 0; i < n; i++)          
     id[i] = i;               //set id of each object to itself

Union

To merge components containing p and q, change all entries whose id equals id[p] to id[q].

int pid = id[p];
int qid = id[p];
for (int i = 0; i < id.length; i++)
    if(id[i] == pid)
        id[i] = qid;

Connected

Check if p and q have the same id.

return id[p] == id[q];

Java Implementation

public class QF
{
    public int[] id;
    
    public QF(int n)
    {
        id = new int[n];
        for (int i = 0; i < n; i++) {
            id[i]=i;
        }
    }
    
    public void union (int p, int q)
    {
        int pid = id[p];
        int qid = id[q];
        for (int i = 0; i < id.length; i++) {
            
            if(id[i] == pid) {
                id[i] = qid;
            }
        }
    }
    
    public boolean connected (int p, int q)
    {
        return id[p] == id[q];
    }
}

Quick Union

It’s an algorithm for solving the dynamic connectivity problem, also called “lazy approach”.

for (int i = 0; i < n; i++)
    parent[i] = i;      //set parent of object at index i

Root

while (i != id[i]) 
  i = id[i];
return i;

Union

To merge components containing p and q, set the id of p’s root to the id of q’s root.

 int i = root(p);
 int j = root(q);
 id[i] = j;

Connected

Check if p and q have same root.

return root(p) == root(q);

Java Implementation 

public class QuickUnionUF
{
    private int[] id;
    public QuickUnionUF(int N)
    {
        id = new int[N];
        for (int i = 0; i < N; i++) 
            id[i] = i;
    }
    public int root(int i)
    {
        while (i != id[i]) i = id[i];
        return i;
    }
    public boolean connected(int p, int q) {
        return root(p) == root(q);
    }
    public void union(int p, int q) {
        int i = root(p);
        int j = root(q);
        id[i] = j;
    }
}