How to connect an action on IBM Cloud Functions with a database? - node.js

I have a conversation in watson assistant and i want be able to call an action from IBM cloud function to make some query on my database (Azure). I'm not familiar with cloud function so this may be a dumb question, i don't understand how to make a connection with the database, i tried write some nodejs code but of course i'm wrong couse it return an "internal error".
I also tried to write some code in python instead of nodejs.
Again this is a dumb question so forgive me. Thank you!
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'my_host',
user: 'my_user',
password: 'my_psw',
database: 'my_db'
});
connection.connect();
rows = connection.query('my_query')
if (!err) {
console.log(typeof(rows));
console.log('The solution is: ', rows);
} else {
console.log(typeof(rows));
console.log('Error while performing Query.');
}
connection.end();
{
"error": "Internal error."
}
import pyodbc as pyodbc
conn = pyodbc.connect('DRIVER={SQL Server};SERVER=my_server;DATABASE=my_db;UID=my_user;PWD=my_pwd')
cursor = conn.cursor()
sql = "my_sql"
cursor.execute(sql)
result = cursor.fetchall()
print(result)
csr = conn.cursor()
csr.close()
del csr
conn.close()
{
"error": "The action did not return a dictionary."
}

The error comes from how you return the result. You need to pack the result into a valid JSON structure.
return {"sqlresult": myresult}
I referenced two tutorials in the comment above. The chatbot tutorial uses Node.js to implement Cloud Functions. Those functions are called from Watson Assistant. Take a look at this action that fetches records from a Db2 database. It opens a database connection, fetches the record(s) and packs them into a JSON structure. That JSON object is then returned to Watson Assistant.
The tutorial also shows how to pass the database credentials into the Cloud Function.

Related

Node.JS PowerBI App Owns Data for Customers w/ Service Principal (set "config.json" from a table in my database)

I'm attempting to refactor the "Node.JS PowerBI App Owns Data for Customers w/ Service Principal" code example (found HERE).
My objective is to import the data for the "config.json" from a table in my database and insert the "workspaceId" and "reportId" values from my database into the "getEmbedInfo()" function (inside the "embedConfigServices.js" file). Reason being, I want to use different configurations based on user attributes. I am using Auth0 to login users on the frontend, and I am sending the user metadata to the backend so that I can filter the database query by the user's company name.
I am able to console.log the config data, but I am having difficulty figuring out how to insert those results into the "getEmbedInfo()" function.
It feels like I'm making a simple syntax error somewhere, but I am stuck. Here's a sample of my code:
//----Code Snippet from "embedConfigServices.js" file ----//
async function getEmbedInfo() {
try {
const url = ;
const set_config = async function () {
let response = await axios.get(url);
const config = response.data;
console.log(config);
};
set_config();
const embedParams = await getEmbedParamsForSingleReport(
config.workspaceId,
config.reportId
);
return {
accessToken: embedParams.embedToken.token,
embedUrl: embedParams.reportsDetail,
expiry: embedParams.embedToken.expiration,
status: 200,
};
} catch (err) {
return {
status: err.status,
error: err.statusText,
}
};
}
}
This is the error I am receiving on the frontend:
"Cannot read property 'get' of undefined"
Any help would be much appreciated. Thanks in advance.
Carlos
The error is because of fetching wrong URL. The problem is with the config for the Service Principal. We will need to provide reportId, workspaceId for the SPA and also make sure you added the service principal to workspace and followed all the steps from the below documentation for the service principal authentication.
References:
https://learn.microsoft.com/power-bi/developer/embedded/embed-service-principal

How to connect to Google Cloud SQL (PostgreSQL) from Cloud Functions?

I feel like I've tried everything. I have a cloud function that I am trying to connect to Cloud SQL (PostgreSQL engine). Before I do so, I pull connection string info from Secrets Manager, set that up in a credentials object, and call a pg (package) pool to run a database query.
Below is my code:
Credentials:
import { Pool } from 'pg';
const credentials: sqlCredentials = {
"host":"127.0.0.1",
"database":"myFirstDatabase",
"port":"5432",
"user":"postgres",
"password":"postgres1!"
}
const pool: Pool = new Pool(credentials);
await pool.query(`select CURRENT_DATE;`).catch(error => console.error(`error in pool.query: ${error}`));
Upon running the cloud function with this code, I get the following error:
error in pool.query: Error: connect ECONNREFUSED 127.0.0.1:5432
I have attempted to update the host to the private IP of the Cloud SQL instance, and also update the host to the Cloud SQL instance name on this environment, but that is to no avail. Any other ideas?
Through much tribulation, I figured out the answer. Given that there is NO documentation on how to solve this, I'm going to put the answer here in hopes that I can come back here in 2025 and see that it has helped hundreds. In fact, I'm setting a reminder in my phone right now to check this URL on November 24, 2025.
Solution: The host must be set as:
/cloudsql/<googleProjectName(notId)>:<region>:<sql instanceName>
Ending code:
import { Pool } from 'pg';
const credentials: sqlCredentials = {
"host":"/cloudsql/my-first-project-191923:us-east1:my-first-cloudsql-inst",
"database":"myFirstDatabase",
"port":"5432",
"user":"postgres",
"password":"postgres1!"
}
const pool: Pool = new Pool(credentials);
await pool.query(`select CURRENT_DATE;`).catch(error => console.error(`error in pool.query: ${error}`));

Looking for Python example to search for a Cognito identity and update attributes

I am integrating a payment solution which uses web hooks. The payment provider is given the Cognito userid (or user sub) during checkout. Upon successful checkout, the payment provider calls a web hook which I've implemented using AWS Lambda/Gateway and Python. Within this web hook I get the payment status and the Cognito user id.
What I'd like to do next is update or set an attribute on the given Cognito user id for the subscription status.
I've found pieces of JavaScript code which seem like they get me sort of there but I am missing something from how this should work. Here is the JS code I found to search for a user:
var cog = new AWS.CognitoIdentityServiceProvider();
var filter = "sub = \"" + userSub + "\"";
var req = {
"Filter": filter,
"UserPoolId": "your pool id" // looks like us-east-9_KDFn1cvys
};
cog.listUsers(req, function(err, data) {
if (err) {
console.log(err);
}
else {
if (data.Users.length === 1){ //as far as we search by sub, should be only one user.
var user = data.Users[0];
var attributes = data.Users[0].Attributes;
} else {
console.log("Something wrong.");
}
}
});
I need a Python version of the above... also I am not quite sure how to initialize the AWS.CognitoIdentityServiceProvider in order to do the search. It seems like I need to have an IAM credentials set up in order to search a user identity pool, no?
Any pointers on how to search for a user in a Cognito identity pool using Python would be appreciated!
Here's how you can search for a user with a prefix:
import json
import boto3
import datetime
client = boto3.client('cognito-idp')
def default(o):
if isinstance(o, (datetime.date, datetime.datetime)):
return o.isoformat()
def lambda_handler(event, context):
response = client.list_users(
UserPoolId='<UserPoolID>',
Limit=1,
Filter='given_name^=\"Xavier\"'
)
return {
'statusCode': 200,
'body': json.dumps(response['Users'],
sort_keys=True,
indent=1,
default=default)
}
You will need to replace the with your actual Cognito User Pool ID.

newbie node.js bot integration with database lookup (looking for best practice)

OK, new to Node.js and botframework. I built first bot using Azure site and downloaded the code. Chose the Luis integrated bot template.
I understand (finally) the event driven model of node.js and the concept of callbacks.
I have the code snippet below. When Luis finds an intent of "Help" it triggers this function. In turn, I have database calls to lookup the entity. Within the database I have an entity, response (if entity is bottle, answer "Recycle").
I have that code working too.
Below the first block is a function handleHelpRequester which is the callback function, I have that working as well. Where I am a little stuck (best practice) is that in this callback function I want to send something to the session object (session.send toward the bottom of the function).
Since I don't create the session object (directly) I'm not sure on the options.
Should I pass the session object to the database function, then pass it back?
Should I create a global variable and set it to the session object (I'm concerned that if multiple people are using this bot then this approach won't work).
I'm open for suggestions.
Thanks
.matches('Help', (session, args) => {
var entities = args.entities;
var itype = builder.EntityRecognizer.findEntity(args.entities, 'ItemTypes');
var respondToUser = '';
var msg = 'Initialized';
// if there is an entity provided, perform a lookup of the entity.
if (itype.entity !== null) {
//Use session.sendTyping so the user thinks something is happening rather than being ignored while we do the lookup in SharePoint.
session.sendTyping();
//perform lookup
respondToUser = sp.lookupEntity(itype.entity, handleHelpRequest);
};
})
function handleHelpRequest(err, respondToUser) {
var msg = 'uninitialized';
if (err = 'success') {
console.log('Respond to user from matches:'.concat(respondToUser));
//return from lookup
if (respondToUser === 'No match found') {
msg = 'I think you are asking for help, but I don\'t understand what you need help with.';
}
else {
msg = 'I can help you with that, \'%s\'.', respondToUser;
}
console.log(msg);
session.send(msg);
//The following two lines are for debugging
session.send('How may I assist you? ' + JSON.stringify(args));
session.send('Value of entity you said: \'%s\'.', itype.entity);
}
else {
console.log('an error occurred');
}
}
If you want to have access to the session object, then pass it as a parameter to your helper function.
Example:
function handleHelpRequest(session, err, respondToUser) {
// do session stuff
}

switching mongodb on request auth issue

i am developing a multitenant app in node that switches db based on the request.
i am using mongoose to create the connection to the mongo deployment where i have 3 dbs.
all my code is written in coffeescript.
here is how i create the initial connection:
conn = mongoose.createConnection('mongodb://<user>:<pwd>#<host>:<port>,<host>:<port>/main?replicaSet=set-xxxxxxxxxx');
here the code in the request
db = conn.useDb('demo')
myModel = db.model('mymodel')
for obj in objects
o = new settingModel(obj)
o.save (err, obj) ->
console.log 'err is', err if err
i can switch db and query the db but when i try to write to it i get a:
errmsg: 'not authorized on demo to execute command { insert: "settings", writeConcern: { w: 1 }...
how can i solve this issue? the databases are all hosted on compose.io

Resources