CF Connect to the cloud controller - javascript

I use the following lib to connect to the cloud controller
https://github.com/prosociallearnEU/cf-nodejs-client
const endpoint = "https://api.mycompany.com/";
const username = "myuser";
const password = "mypass";
const CloudController = new (require("cf-client")).CloudController(endpoint);
const UsersUAA = new (require("cf-client")).UsersUAA;
const Apps = new (require("cf-client")).Apps(endpoint);
CloudController.getInfo().then((result) => {
UsersUAA.setEndPoint(result.authorization_endpoint);
return UsersUAA.login(username, password);
}).then((result) => {
Apps.setToken(result);
return Apps.getApps();
}).then((result) => {
console.log(result);
}).catch((reason) => {
console.error("Error: " + reason);
});
I try to run it against our API and its not working and Im not getting no error message in the console, what it can be ?
where does the space/org is handled here ? since when I connect from the cli it ask me to which space/org I want to connect...
Im able to login via the CLI, just from the code I cant, any idea what is missing here?
The issue it when I run it I dont get any error that can help to understand what is the root cause

I cloned the original git repository and modified some methods to support proxy. Please note that I modified just some methods to get the sample code working, but a complete refactor of the package is needed.
Basically what you have to do is to add a proxy parameter before calling the request method (this is done throughout the package, so several modifications are needed), for example this is for one of the methods in the Organization.js file:
getSummary (guid) {
const url = `${this.API_URL}/v2/organizations/${guid}/summary`;
const proxy = `${this.API_PROXY}`;
const options = {
method: "GET",
url: url,
proxy: proxy,
headers: {
Authorization: `${this.UAA_TOKEN.token_type} ${this.UAA_TOKEN.access_token}`
}
};
return this.REST.request(options, this.HttpStatus.OK, true);
}
You can find my changes in the git repository below:
https://github.com/adasilva70/cf-nodejs-client.git
I have also created a new sample below. This sample lists all organizations for a user, gets the first organization returned and lists its spaces. You can modify the code to provide a similar functionality that cf login provides (allow you to select an organization then a space).
const endpoint = "https://api.mycompany.com/";
const username = "youruser";
const password = "yourpassword";
const proxy = "http://proxy.mycompany.com:8080";
const CloudController = new (require("cf-nodejs-client")).CloudController(endpoint, proxy);
const UsersUAA = new (require("cf-nodejs-client")).UsersUAA;
const Apps = new (require("cf-nodejs-client")).Apps(endpoint, proxy);
const Orgs = new (require("cf-nodejs-client")).Organizations(endpoint, proxy);
CloudController.getInfo().then((result) => {
console.log(result);
UsersUAA.setEndPoint(result.authorization_endpoint, proxy);
return UsersUAA.login(username, password);
}).then((result) => {
//Apps.setToken(result);
//return Apps.getApps();
Orgs.setToken(result);
return Orgs.getOrganizations();
}).then((result) => {
console.log(result);
org_guid = result.resources[1].metadata.guid;
return Orgs.getSummary(org_guid);
}).then((result) => {
console.log(result);
}).catch((reason) => {
console.error("Error: " + reason);
});
I have done just minor tests to make sure the sample works, so use carefully. Also, the changes will only work for a case where proxy is needed now.

The first thing that strikes me on the library's github site is the warning:
Note: This package is not ready for a production App yet.
It also seems that the project is not being maintained as there are a number of tickets ooened that are quite a few months old that don't have a response.
Anyway, to figure out why the library is not working and producing no error message, I would check out the library source code and add some console logging statements, probably starting with the HttpUtils. For example:
requestWithDefaults(options, function (error, response, body) {
console.log("requestWithDefaults error: ", error)
console.log("requestWithDefaults response: ", response)
console.log("requestWithDefaults body: ", body)
...
}
Alternatively, you could try debugging the code by adding breakpoints to the requestWithDefaults and other key places in the library, using the nodejs debugger.
You could also try debugging the network calls similar to this how to monitor the network on node.js similar to chrome/firefox developer tools?
To understand how to use the library, I would take a look into the tests folder and look for a test that is similar to your use case. There are a reasonable amount if tests that look useful in the test/lib/model/cloudcontroller folder.
As for the question about spaces, I have found an example where you can pass in a space guid to return apps for that space guid.
CloudFoundrySpaces.getSpaceApps(space_guid, filter).then( ... )
I'm assuming the call you are using App.getApps() will return Apps for all spaces/organizations.

Related

Get a particular URL in Node JS other ways

I have a REST API of Reddit. I am trying to parse the JSON output to get the URL of the responses. When I try to send the request, I get multiple outputs, but I am not sure how to do it as it's a random response.
https
.get("https://www.reddit.com/r/cute/random.json", resp => {
let data = "";
resp.on("data", chunk => {
data += chunk;
});
const obj = JSON.parse(data);
resp.on("end", () => {
console.log(obj.url);
});
})
.on("error", err => {
console.log("Error: " + err.message);
});
This is the code I have got. I used the default Node's http library and I don't think it worked. I have never used any Node Libraries, so it will be helpful if you can suggest them too. And also let me know if what I have done is right.
I understand that http is a core library of Node JS, but I strongly suggest you to use something like node-fetch. Make sure you run the following command on your terminal (or cmd) where your package.json file exists:
$ npm install node-fetch
This will install the node-fetch library, which acts similarly to how the Web based fetch works.
const fetch = require("node-fetch");
const main = async () => {
const json = await fetch("https://www.reddit.com/r/cute/random.json").then(
res => res.json()
);
console.log(
json
.map(entry => entry.data.children.map(child => child.data.url))
.flat()
.filter(Boolean)
);
};
main();
The URLs that you are looking for, I could find in the data.children[0].data.url so I did a map there. I hope this is something that might help you.
I get multiple output for the same code, run multiple times, because the URL you have used is a Random Article Fetching URL. From their wiki:
/r/random takes you to a random subreddit. You can find a link to /r/random in the header above. Reddit gold members have access to /r/myrandom, which is right next to the random button. Myrandom takes you to any of your subscribed subreddits randomly. /r/randnsfw takes you to a random NSFW (over 18) subreddit.
The output for me is like this:
[ 'https://i.redd.it/pjom447yp8271.jpg' ] // First run
[ 'https://i.redd.it/h9b00p6y4g271.jpg' ] // Second run
[ 'https://v.redd.it/lcejh8z6zp271' ] // Third run
Since it has only one URL, I changed the code to get the first one:
const fetch = require("node-fetch");
const main = async () => {
const json = await fetch("https://www.reddit.com/r/cute/random.json").then(
res => res.json()
);
console.log(
json
.map(entry => entry.data.children.map(child => child.data.url))
.flat()
.filter(Boolean)[0]
);
};
main();
Now it gives me:
'https://i.redd.it/pjom447yp8271.jpg' // First run
'https://i.redd.it/h9b00p6y4g271.jpg' // Second run
'https://v.redd.it/lcejh8z6zp271' // Third run
'https://i.redd.it/b46rf6zben171.jpg' // Fourth run
Preview
I hope this helps you. Feel free to ask me if you need more help. Other alternatives include axios, but I am not sure if this can be used on backend.

Use git credential manager to fetch azure devops api instead of personal access token

I am trying to fetch git azure devops api to get information about repositories and branches in js.
In order to achieve that, I made a little application with the following code :
$(document).ready(function() {
var personalToken = btoa(':'+'<personnalAccessToken>');
fetch('https://dev.azure.com/<company>/<project>/_apis/git/repositories?api-version=5.1', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
'Authorization': 'Basic '+ personalToken
}
}).then(function(response) {
return response.json();
}).then(function(repositories) {
console.log("There are "+repositories.count+" repositories");
}).catch(function(error) {
console.log('Fetch error: ' + error.message);
});
This code is working great but as you can see there is my personnalAccessToken writen directly inside the code... which is really bad...
When I am using git in command line, I don't have to specify any credential information because I use git credential manager for windows. Which means my personnalAccessToken is already stored, cached and automatically used everytime I use a git command, like clone, etc.
So, I would like my js code to use the same thing, I would like it to use my stored credentials automatically to fetch the api without being required to set my personnalAccessToken in code.
I have already searched for hours but can't find out if it is possible.
I have already searched for hours but can't find out if it is
possible.
Sorry but as I know it's impossible. The way you're calling the Rest API is similar to use Invoke-RestMethod to call rest api in Powershell.
In both these two scenarios, the process will try to fetch PAT for authentication in current session/context and it won't even try to search the cache in Git Credential Manager.
You should distinguish the difference between accessing Azure Devops service via Rest API and by Code:
Rest API:
POST https://dev.azure.com/{organization}/{project}/{team}/_apis/wit/wiql?api-version=5.1
Request Body:
{
"query": "Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.WorkItemType] = 'Task' AND [State] <> 'Closed' AND [State] <> 'Removed' order by [Microsoft.VSTS.Common.Priority] asc, [System.CreatedDate] desc"
}
Corresponding Code in C#:
VssConnection connection = new VssConnection(new Uri(azureDevOpsOrganizationUrl), new VssClientCredentials());
//create http client and query for resutls
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();
Wiql query = new Wiql() { Query = "SELECT [Id], [Title], [State] FROM workitems WHERE [Work Item Type] = 'Bug' AND [Assigned To] = #Me" };
WorkItemQueryResult queryResults = witClient.QueryByWiqlAsync(query).Result;
Maybe you can consider using a limited PAT, limit its scope to Code only:
I know there exists other Authentication mechanism
:
For Interactive JavaScript project: ADALJS and Microsoft-supported Client Libraries.
You can give it a try but I'm not sure if it works for you since you're not using real Code way to access the Azure Devops Service... Hope it makes some help :)
If you have the script set up in an Azure Runbook you can set it as an encrypted variable there and have it pull it from there before running rather than having it directly written into the code.
$encryptedPatVarName = "ADO_PAT"
$adoPat = Get-AutomationVariable -Name $encryptedPatVarName
$adoPatToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($adoPat)"))
$adoHeader = #{authorization = "Basic $adoPatToken"}
The above is the Powershell version of it. I have seen some people do it with other

Nodejs mssql/msnodesqlv8 issue sending semicolon in database request

Attempting to build a basic API to interact with a MSSQL v12 database using Nodejs. I have been able to connect to the database using the mssql/msnodesqlv8 package but parameterized queries are failing with the following.
code: 'EREQUEST',
number: 102,
state: undefined,
originalError:
{ Error: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near ''. sqlstate: '42000', code: 102 },
name: 'RequestError' }
Debug: internal, implementation, error
I used SQL Server Profiler and saw that the query was coming in as such
exec sp_executesql N'declare #SecurityKey nvarchar (MAX);set #SecurityKey=#P1;exec database.getSecurityBySecurityId #SecurityKey;',N'#P1 nvarchar(20)',N'XXXXXXXX'
and failing. After some investigation it seems to be an issue with the semicolons after the declare and set statements as it is not allowed in TSQL (very new to MSSql, will need to read up). Removing the semicolons did indeed fix the issue when I ran the query manually.
So my question is this.. is there a way to get msnodesqlv8 to work with my version on |Mssql and if yes, how so? Is there a way to omit these semicolons.
If you think there is a better way, i would like to hear it as I am new to Nodejs + MSSql.
Contents of getSecurity.sql
exec database.getSecurityBySecurityId #SecurityKey
contents of index.js
"use strict";
const utils = require("../utils");
const api = async ({ sql, getConnection }) => {
const sqlQueries = await utils.loadSqlQueries("events");
const getSecurity = async SecurityKey => {
const cnx = await getConnection();
const request = await cnx.request();
request.input('SecurityKey', SecurityKey);
return request.query(sqlQueries.getSecurity);
};
return {
getSecurity
};
};
module.exports = { api };
I was able to work around this by editing the library.
In ./lib/msnodesqlv8.js you can find where is concatenates the query string
...
}
if (input.length) command = `declare ${input.join(',')} ${sets.join(';')};${command};`
if (output.length) {
command += `select ${output.join(',')};`
handleOutput = true
}
....
Editing this will allow you to control the flow.

nodejs-dialogflow library returning TypeError: dialogflow.SessionsClient is not a constructor

I am trying to make a script that takes input from the user, runs it through Dialogflow, then returns it back to the user. The platform I am taking input from only supports Node.js. I am hosting the bot through glitch.com, but I don't think that's what's causing the issue. I wanted to check on here before I submit a bug report onto the GitHub repo.
var bot = 'the platform i use to accept inputs and send outputs'
bot.on("message", async message => {
console.log(message.content); // Log chat to console for debugging/testing
if (message.content.indexOf(config.prefix) === 0) { // Message starts with your prefix
let msg = message.content.slice(config.prefix.length); // slice of the prefix on the message
let args = msg.split(" "); // break the message into part by spaces
let cmd = args[0].toLowerCase(); // set the first word as the command in lowercase just in case
args.shift(); // delete the first word from the args
// You can find your project ID in your Dialogflow agent settings
const projectId = process.env.PROJECT_ID; //https://dialogflow.com/docs/agents#settings
const sessionId = 'quickstart-session-id';
var query = msg;
const languageCode = 'en-US';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
}
return;
});
That is the relevant part of the code. For those wondering, the process.env.PROJECT_ID is something glitch.com uses for anything private. Because I don't want random people getting their hands on my project id, I hide it in there and glitch hides it from anyone I don't explicitly invite.
Every time I execute this and try to query the bot, it returns an error Uncaught Promise Error: TypeError: dialogflow.SessionsClient is not a constructor.
If someone can direct me to what I'm missing, or what the problem is, that would be great!
As per #google-cloud/dialogflow - npm
IMPORTANT NOTE
Version 2.0.0 renames dialogflow to #google-cloud/dialogflow on npm, along with introducing TypeScript types.
So to update the dialogflow to use latest version, first uninstall dialogflow and then install with following command:
npm uninstall dialogflow
npm i #google-cloud/dialogflow
Also, if you were using older version 1.2.0 of dialogflow before then in code, make following changes as per their sample or refer the sample from above link (in require and to get the sessionPath):
const dialogflow = require('#google-cloud/dialogflow');
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
It worked fine for me after doing this without any errors.
I figured it out. After many many refreshes, I decided to look at the npm documentation for it. Turns out some idiot listed the earliest version as 4.0.3, and the latest version as 0.7.0. I needed to explicitly tell it to use version 0.7.0 in order for it to work. Thank goodness!
Mine worked by reinstalling the dialogflow package
npm uninstall dialogflow
npm install dialogflow --save
put the code inside try and catch block. In my case by doing this, this error was removed.

How to log the AWS Amplify API.get request to view queryStringParameters on url

I'm not sure how to log / see the actual request that is being made.
I can look at this code below and assume that it's http://myendpoint.com?my/path?param=value, however with more complex code and variables in other places, how can I tell what exactly is getting called via API.get?
The main reason I ask is because I don't think my query parameters are being appended to my request, and I'm hoping to confirm.
const apiName = 'http://myendpoint.com'
const path = '/my/path'
const myInit = {
queryStringParameters: {
param: 'value'
}
}
API.get(apiName, path, myInit)
.then((response) => {
console.log('> > > PLEASE TELL ME HOW TO LOG THE REQUEST < < <')
resolve(response)
},
(err) => {
console.log('err resp', err)
resolve(err)
})
Edit: FYI this is in a REACT NATIVE project, so things like the Chrome Network tab are of no use unfortunately.
Okay, I actually think I figured this out, and it boiled down to two different things:
1. ADDING THE AMPLIFY LOGGER:
I found there is an Amplify logger via:
https://github.com/aws/aws-amplify/blob/master/media/logger_guide.md
So I added:
Amplify.Logger.LOG_LEVEL = 'DEBUG'
and now when I am debugging in VS Code I'm seeing the request URL being logged.
2. REALIZING 'queryStringParameters' ISN'T ACTUALLY SUPPORTED: .
I was looking through the Amplify GitHub repo issues and found out that queryStringParameters isn't actually supported yet, which is fun.
URL to issue: https://github.com/aws/aws-amplify/issues/127 .
So instead I appended all my query parameters onto the path, and that works:
const apiName = 'http://myendpoint.com'
const path = `/my/path?param=${value}`
API.get(apiName, path)
.then((response) => {
resolve(response)
},
(err) => {
console.log('err resp', err)
resolve(err)
})
I am now seeing the request URL logged, and seeing the parameters as a part of the request.

Categories

Resources