Google cloud functions in python to read firebase realtime data - python

I'm writing a simple Google Cloud Function to learn, with the new Python3.7 option, and I would like to read/write some data to Firebase Realtime db.
I found some information to use Firestore that worked, but now I need to use the realtime Database.
# global
import firebase_admin
from firebase_admin import db
# from firebase_admin import firestore
default_app = firebase_admin.initialize_app()
def check_prices_updates(request):
"""Responds to any HTTP request.
Args:
request (flask.Request): HTTP request object.
Returns:
The response text or any set of values that can be turned into a
Response object using
make_response
"""
collection = 'pricelist'
mybase = db.reference(collection)
....[other code]
return "OK"
This is an excerpt of my code, the documentation says that the initialize_app() must be left empty to collect the project default credentials.
The line where I call db.reference(collection) give me the exception:
ValueError: Invalid databaseURL option: "None". databaseURL must be a non-empty URL string.
as if the configuration parameters did not show the requested key 'databaseURL'. With Firestore, as example I could call firestore.client(), after the import from firebase_admin, adding 'google-cloud-firestore in requirements.txt.
Now, for firebase, what should I fix to read and write on the db?
PS. on my db the ".read" rule is true for all so I haven't trouble on auth!
UPDATE:
After a good sleep I realized that to access the realtime db I need to pass some options to initialize_app, as follow:
firebase_admin.initialize_app(options={'databaseURL': 'https://[PROJECT-NAME].firebaseio.com'})
Cheers

Initiliase the Firebase Admin SDK
This will access the db, even if you put permission restrictions on read, write, as your python will have admin access
If you have multiple database instance (Only available for blaze plan)
Initilise them with different app name inside single python script
#Firebase Admin Imports
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
#Firebase admin sdk Key - Save it as secret
firebaseval={
"type": "service_account",
"project_id": "<project_id>",
"private_key_id": "<private_key>",
"private_key": "-----BEGIN PRIVATE KEY--xxxxxxxxxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-ipcf5#<project_id>.iam.gserviceaccount.com",
"client_id": "<clinet_id>",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-ipcf5%40<project_id>.iam.gserviceaccount.com"
}
cred = credentials.Certificate(firebaseval)
print("\n---------------------------")
print("Initialising Firebase...")
#Initilising Database 1- fetching stock and option details
firebase_admin.initialize_app(cred, {
'databaseURL' : 'https://<project_id>-<instance_id1>.firebaseio.com/'
})
# Initilising Database 2- Different instance ID
app2 = firebase_admin.initialize_app(cred, {
'databaseURL': 'https://<project_id>-<instance_id2>..firebaseio.com/'
}, name='app2')
# Initilising Database 3- Different instance ID
app3 = firebase_admin.initialize_app(cred, {
'databaseURL': 'https://<project_id>-<instance_id3>..firebaseio.com/'
}, name='app3')
print("Initialised Firebase")
print("---------------------------\n")
Accessing the different database Instances
# database instance_id2
mainref2=db.reference("PATH",app2)
# database instance_id3
mainref3==db.reference("PATH",app3)
# Reading whole data from
mainref2.get()
# Reading inside child node from db instance_id2
mainref2.child("child_name").get()
# Setting json data to db instance_id3
mainref3.set({"data":"something"})

Related

How to access firebase database without having 'Realtime Database'?

Im trying to connect my python script to a Firebase database.
Here is the code:
import firebase_admin
from firebase_admin import credentials, db
cred = credentials.Certificate("irebase-adminsdk-ofcmd-bwd7fbcz2c.json")
firebase_admin.initialize_app(cred, {'databaseURL':'https://company.firebaseio.com/'})
ref = db.reference('/users').get()
The ERROR Im facing looks like this:
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://company.firebaseio.com/users.json
I did a lot of research and everyone says that I have to find the right URL in the 'Realtime Database' Section. I wonder if there is any way to access the Firebase db without having realtime one enabled.
if you are looking to access the Firebase Database without having the realtime one enabled, you can try the Cloud Firestore which is a different database service provided by Firebase which doesn't require realtime database to be enabled but you may need to change the way you are accessing the data
import firebase_admin
from firebase_admin import credentials, firestore
# Initialize the Firebase Admin SDK with your service account credentials
cred = credentials.Certificate("firebase-adminsdk-that-cred-file.json")
firebase_admin.initialize_app(cred)
# Create a reference to the Firestore database
db = firestore.client()
# Read data from a specific document in the 'users' collection
doc_ref = db.collection('users').document('user1')
doc = doc_ref.get()
# Print the data from the document
print(doc.to_dict())

Cant find my firebase real-time database when trying to import data in python

import pandas as pd
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate("crt")
firebase_admin.initialize_app(cred,{
'databaseURL': 'url'
})
db = firestore.client()
actor_ref = db.collection('actors')
# Import data
df = pd.read_csv("./hw1_datasets/actor.csv")
tmp = df.to_dict(orient='records')
list(map(lambda x: actor_ref.add(x), tmp))
I'm running this script to import csv to my Firebase Real-time Database and it keeps saying the project does not exist or it does not contain an active Cloud Datastore or Cloud Firestore database. I created a firebase real-time database by using the same google account and I'm not sure why is it saying no database. Does Google Cloud not support Firebase's real-time database? Any help would be strongly appreicated
Your question seems to be mixing up both Firebase Realtime Database and Firestore. While you have mentioned that you are using Firebase Realtime Database your python script is for importing data into Firestore. Please note that Firestore and Firebase Realtime Database are two different Databases.
The error message you are getting suggests that the project doesn’t have a Firestore Database. So to resolve the error please go to Firebase Console and create a Database in Firestore. After creating the Firestore database add a collection named ‘actors’. You can follow the steps mentioned here to create a Firestore database in Firebase Console.
If you want to use Firebase Realtime database you have to initialize it in the python script differently. You may look at the following as a reference to know how to initialize Firebase Realtime Database.
First you have to import ‘db’ from firebase_admin as follows
from firebase_admin import db
Then you have to create a credentials object by taking the serviceAccountKey.json file which you can generate in the Project Overview > Project Settings page in Firebase console
cred = credentials.Certificate('path/to/serviceAccountKey.json')
Next you have to initialize the database as follows -
firebase_admin.initialize_app(cred, {
'databaseURL': 'https://databaseName.firebaseio.com'
})
Now to access the Firebase Realtime Database you have to create a reference as follows
ref = db.reference('databaseName')
More details on how to initialize Firebase Realtime Database is here.
To read and save data to the Firebase Realtime Database you may refer to this document and this document respectively.
The problem is in:
firebase_admin.initialize_app(cred,{
'databaseURL': 'url'
})
The databaseURL is a reference to the Realtime Database, and it seems that is not enough for your code to find the Firestore database of the project. As shown in the documentation on setting up Python access to Firestore, you will (also) need to pass the project ID before you can access Firestore:
firebase_admin.initialize_app(cred, {
'projectId': project_id,
})
db = firestore.client()

How to make cloud firestore rules work on python program?

I written rules for my firestore documents and using admin sdk credentials, that bypasses rules.
How to make rules work on python?
Python code
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('key.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
try:
doc_ref = db.collection('users').document('test')
doc_ref.set({'password':'testPass','shadow':'testShadow'})
print('success')
except:
print('failed')
Firestore rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}
}
}
The Firebase Admin SDKs run with administrative privileges and bypass the security rules for Firestore. There is no way to change that.
If you want your code to follow the security rules, you'll have to use one of the client-side SDKs, but none exists for Python at the moment.

authenticate google API without a config file

I am trying to authenticate google API without a config file, I can't even find proof it is possible other than old code in my service that wasn't used in years.
My class receive this dict:
self._connection_data = {
"type": args,
"project_id": args,
"private_key_id": args,
"private_key": args,
"client_email": args,
"client_id": args,
"auth_uri": args,
"token_uri": args,
"auth_provider_x509_cert_url": args,
"client_x509_cert_url": args
}
and the code is -
from google.cloud import bigquery
from google.oauth2 import service_account
def _get_client(self):
credentials = service_account.Credentials.from_service_account_info(self._connection_data)
return bigquery.Client(project=self._project_id, credentials=credentials, location='US')
I receive the error
'{"error":"invalid_grant","error_description":"Invalid grant: account not found"}
however, everything works when I use a helper file for the configs called config.json and an OS environmentnt variable:
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = "config.json"
self.job_config = bigquery.QueryJobConfig()
self.job_config.use_legacy_sql = True
return bigquery.Client()
I don't want a solution with the env variable, I would like to use the Credentials class without a file path
Well In the end I managed to make my code work without any need for the global variable or a file path. I had a problem with my configured credentials...
This is the code -
# init class here
self.job_config = bigquery.QueryJobConfig()
self.job_config.use_legacy_sql = True
def _get_client(self):
credentials = service_account.Credentials.from_service_account_info(self._connection_data)
return bigquery.Client(project=self._project_id, credentials=credentials)
# function to get columns
query_job = self._get_client().query(query, job_config=self.job_config)
results = query_job.result(timeout=self._current_timeout)
The only part I was missing was to send the QueryJobConfig class with legacy SQL set to true in all of my queries.
Unfortunately, there are no other methods to authenticate your API request without either using an environment variable or specifying the key file path. There are some ways of authenticating your request with GCP using a key json file. Before anything, you should set up your service account and download the json file with your key, as described here.
Then, the first method is using default credentials, according to the documentation:
If you don't specify credentials when constructing the client, the
client library will look for credentials in the environment.
That means, you just need to set your environment variable. Then, the Google Client Library will determine the credentials implicitly. In addition, it also allows you to provide credentials separately from your application, which eases the process of making changes in the code. You can set the environment variable as follows:
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json"
After setting it, you would be able to run the following code:
def implicit():
from google.cloud import storage
# If you don't specify credentials when constructing the client, the
# client library will look for credentials in the environment.
storage_client = storage.Client()
# Make an authenticated API request
buckets = list(storage_client.list_buckets())
print(buckets)
Secondly, you can specify the file path within your code using the [google.oauth2.service_account][3] module. It is stated in the documentation that:
An OAuth 2.0 client identifies the application and lets end users
authenticate your application with Google. It allows your application
to access Google Cloud APIs on behalf of the end user.
In order to use the module, you can use one of both codes:
#It creates credentials using your .json file and the Credentials.from_service_account_file constructor
credentials = service_account.Credentials.from_service_account_file(
'service-account.json')
Or
#If you set the environment variable, you can also use
#info = json.loads(os.environ['GOOGLE_APPLICATION_CREDENTIALS_JSON_STRING'])
#Otherwise, you specify the path inside json.load() as below
service_account_info = json.load(open('service_account.json'))
credentials = service_account.Credentials.from_service_account_info(
service_account_info)
Finally, I encourage you to check the Authentication strategies in the documentation.

Python REST API gives Internal Server Error

I'm trying to create a REST API in python .. I have decent experience in python but relatively new to REST APIs ... When I run my python script I get a "Internal Server Error" on my browser ..
Some thing like this:
Error on the browser
and on my console I see this:
Error as displayed on my console
Here's my code:
from flask import Flask, request
from flask_restful import Resource, Api
import firebase_admin
# For connecting to firestore database and authentication
from firebase_admin import credentials, firestore
# For Data base Connectivity
from firebase_admin import db
from flask import jsonify
app = Flask(__name__)
api = Api(app)
class Firebase_Data(Resource):
def getData(self):
# Setting up credentials to connect
cred = credentials.Certificate(../Path)
# Setting up secure connection to firestore Real time database
app = firebase_admin.initialize_app(cred, {
'projectId' : 'project_ID'
})
# Connecting to the firestore client
db_ref = firestore.client()
# Referring to the '** section of the data
ref_inc = db_ref.collection(u'name of column')
# Fetching all the records under that particular section and
converting them to list of dictionaries
docs = list( ref_inc.get() )
lat_long = []
for doc in docs:
data = doc.to_dict()
lat_long.append(
{ 'Latitude:' : data['latitude'], 'Longitude' :
data['longitude'] } )
return jsonify(lat_long)
api.add_resource(Firebase_Data, '/Firebase_Data') # Route_1
if __name__ == '__main__':
app.run(port=5002)
I'm basically trying to fetch some data from a Fire store database and display it on the browser. I don't think the fire store part has anything to do with my error, I think I'm missing something on executing the "get" function of my python class which I'm not able to figure out .. Any help is highly appreciated.. Thanks in advance

Categories