Node ARI Client | Connect method not firing callback? - javascript

So, I've started playing with the Asterisk Restful Interface (ARI).
I have created a separate express app to do this.
I have a correctly configured instance of Asterisk 13 running. I know this because When I go to https://192.168.46.122:8088/ari/sounds in my browser, I am prompted for a username and password, which when entered, returns a valid JSON object back with the expected data...
[
{
"id": "conf-now-unmuted",
"text": "The conference is now unmuted.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "vm-nomore",
"text": "No more messages.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "vm-review",
"text": "press 1 to accept this recording press 2 to listen to it press 3 to rerecord your message",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "demo-echodone",
"text": "The echo test has been completed.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "confbridge-rest-talk-vol-out",
"text": "...to reset your speaking volume to the default level.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
}, ...... etc etc
In my app.js file I have included the following code...
...
var logger = require('morgan');
var client = require('ari-client');
var url = 'https://192.168.46.122:8088/ari/sounds';
var username = 'correct_username';
var password = 'correct_password';
client.connect(url, username, password, function (err, ari) {
console.log('HELLLLLLOOOOO!!');
});
...
The issue, is that the anon callback is never fired. I never see 'HELLLLLLOOOOO!!'
Can anyone shed any light on why/under what circumstances this could happen? Are there any known bugs with the module that could be causing this?
Please let me know if you need further information about config, environment etc.
Thanks guys
UPDATE
Following comments below... I have tried the following:
client.connect(url, username, password)
.then(function(ari) {
console.log('HELLLLLLOOOOO!!');
})
.catch(function(err){
console.log('ERR: ' + err);
});
AND
client.connect(url, username, password, function (err, ari) {
if(err) console.log(err);
console.log('HELLLLLLOOOOO!!');
});
No error and no 'HELLLLLOOOOOO!!' at any point :-(
UPDATE 2
Have just visited /ari/api-docs/resources.json and got the following response... so it looks like it is present.
{
"_copyright": "Copyright (C) 2012 - 2013, Digium, Inc.",
"_author": "David M. Lee, II <dlee#digium.com>",
"_svn_revision": "$Revision: 430337 $",
"apiVersion": "1.7.0",
"swaggerVersion": "1.1",
"basePath": "http://192.168.46.122:8088/ari",
"apis": [
{
"path": "/api-docs/asterisk.{format}",
"description": "Asterisk resources"
},
{
"path": "/api-docs/endpoints.{format}",
"description": "Endpoint resources"
},
{
"path": "/api-docs/channels.{format}",
"description": "Channel resources"
},
{
"path": "/api-docs/bridges.{format}",
"description": "Bridge resources"
},
{
"path": "/api-docs/recordings.{format}",
"description": "Recording resources"
},
{
"path": "/api-docs/sounds.{format}",
"description": "Sound resources"
},
{
"path": "/api-docs/playbacks.{format}",
"description": "Playback control resources"
},
{
"path": "/api-docs/deviceStates.{format}",
"description": "Device state resources"
},
{
"path": "/api-docs/mailboxes.{format}",
"description": "Mailboxes resources"
},
{
"path": "/api-docs/events.{format}",
"description": "WebSocket resource"
},
{
"path": "/api-docs/applications.{format}",
"description": "Stasis application resources"
}
]
}
I'm now thinking it may be an SSL issue?!

Your connection is failing (for reasons outlined below), and because of an issue / upcoming-feature in node-ari-client, the failed connection is not logged.
The node-ari-client module uses Swagger, which expects to load a JSON schema describing an API. In the node-ari-client implementation, Swagger expects to find this JSON schema at %s//%s/ari/api-docs/resources.json.
So, the first thing to check is whether or not this exists / is accessible in your application:
https://192.168.46.122:8088/ari/api-docs/resources.json
There could be several reasons why this would not be available, but most likely the problem is authentication. You mention that when visiting your URL you are "prompted for a username and password". If your JSON schema (or any other files that need to be accessed without credentials) are behind authentication, you are going to need to rethink your application structure.
Currently, if there is a connection failure before Swagger has loaded the JSON schema, node-ari-client will fail silently. There is a Pull Request waiting which addresses this issue and would log the error, but in the meantime you should address the underlying issues which are preventing the connection.
If you can successfully access resources.json, there may be other issues with accessing resources. The URL you describe is accessing your service over https, but your resources.json file is telling Swagger to access it over regular http. To handle this, you could try:
Changing the basePath in your Swagger schema to use https:
"basePath": "https://192.168.46.122:8088/ari",
Adding a protocols field to your Swagger schema:
"protocols":["http", "https"]
Removing https
This is probably a good option in order to discover if https is the cause of the connection issue. Simply keep the Swagger schema exactly as is and try accessing / connecting to your services over http. Does this make a difference?

Related

AWS Security Hub API does not return Latitude and Longitudes

I am working on a project which needs to display the identified AWS security threats on a globe. They have specifically asked to use Security Hub API to get the GaurdDuty, Firewall etc. identified threats by integrating them to Security Hub. We were able to correctly integrate that part and it's working fine. However, in order to display this security threat in a globe it is a must to get the latitude and longitude of the location it occurred. Even though GuardDuty identifies these location it is not returned with Security Hub API response as they mention.
For example I referred https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_GetFindings.html
Here they mention that response will contain an Action field which contains all the remote IP details. But in my case this field is null for the GuardDuty incident I created. However, this as a GuardDuty product field it is returning these data. Just wanted to check whether there's anything I am missing in here.
I am expecting to see following fields in the Security Hub API response for an identified GuardDuty incident.
"Action": {
"ActionType": "string",
"AwsApiCallAction": {
"AffectedResources": {
"string" : "string"
},
"Api": "string",
"CallerType": "string",
"DomainDetails": {
"Domain": "string"
},
"FirstSeen": "string",
"LastSeen": "string",
"RemoteIpDetails": {
"City": {
"CityName": "string"
},
"Country": {
"CountryCode": "string",
"CountryName": "string"
},
"GeoLocation": {
"Lat": number,
"Lon": number
},
"IpAddressV4": "string",
"Organization": {
"Asn": number,
"AsnOrg": "string",
"Isp": "string",
"Org": "string"
}
},
"ServiceName": "string"
},
I used the #aws-sdk/client-securityhub npm package to write the program to invoke security hub API.
Following is the Javascript code I used in here.
const { SecurityHubClient, GetFindingsCommand } = require("#aws-sdk/client-securityhub");
const client = new SecurityHubClient({
region: "ap-south-1",
credentials: {
accessKeyId: "",
secretAccessKey: ""
}
});
const params = {
/** input parameters */
"Filters": {
"ProductName": [
{
"Comparison": "EQUALS",
"Value": "GuardDuty"
}
],
}
};
const command = new GetFindingsCommand(params);
async function getAllSeucrityHubFindings(){
try {
const data = await client.send(command);
console.log(JSON.stringify(data));
} catch (error) {
console.log(error);
} finally {
}
}
getAllSeucrityHubFindings();
It's highly appreciated if someone can help me to resolve this issue.
Thanks in advance

Azure Function Table Storage output binding using an identity-based connection

I'm trying to configure an Azure Table Storage output binding for an Azure Function (in JavaScript) using an identity-based connection instead of a connection string. I believe I've setup the Function as per the docs but I'm getting this error:
System.Private.CoreLib: Exception while executing function: Functions.AzureTvDataFetcher. Microsoft.Azure.WebJobs.Extensions.Storage: Storage account connection string 'AzureWebJobsAzuretvTableStorageConnection' does not exist. Make sure that it is a defined App Setting.
The error mentions that it should be a defined app setting, which it is. This is my local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzuretvTableStorageConnection__tableServiceUri": "https://<account-name>.table.core.windows.net"
}
}
And these are the triggers/bindings defined in function.json:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "table",
"tableName": "azuretv",
"name": "azuretvTableBinding",
"direction": "out",
"connection": "AzuretvTableStorageConnection"
}
]
}
The docs mention that it requires the extension bundle version 2.x, which is installed, see my host.json:
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[2.*, 3.0.0)"
},
So I'm not sure what I'm doing wrong. If I use a connection string instead it works fine. I've also deployed the Function app, created a managed identity for it and assigned the Storage Table Data Contributor role to the storage account but I still get the same error. Any ideas?

How to POST relation in Strapi

I'm trying to do a POST to the Strapi API and can't seem to figure out how to attach a 'has and belongs to many' (many to many) relationship.
I've already tried the following body's:
events: ["ID", "ID"]
name: "name"
&
events: [ID, ID]
name: "name"
Which regarding the docs should be right, I think.
There's no error, I get a '200 OK' response. It adds the record but without the relations.
Event.settings.json:
{
"connection": "default",
"collectionName": "events",
"info": {
"name": "event",
"description": ""
},
"options": {
"increments": true,
"timestamps": [
"created_at",
"updated_at"
],
"comment": ""
},
"attributes": {
"name": {
"type": "string"
},
"artists": {
"collection": "artist",
"via": "events",
"dominant": true
}
}
}
Artist.settings.json:
{
"connection": "default",
"collectionName": "artists",
"info": {
"name": "artist",
"description": ""
},
"options": {
"increments": true,
"timestamps": [
"created_at",
"updated_at"
],
"comment": ""
},
"attributes": {
"name": {
"required": true,
"type": "string"
},
"events": {
"collection": "event",
"via": "artists"
}
}
}
I'm using the standard SQLite database, strapi version 3.0.0-beta.13 and tried the request through Postman, HTML & curl.
I would love to know how to attach the relation on POST
Update 23-07:
Did a fresh install of Strapi and now everything is working.
I think it's because your set you ID as a String instead of an Integer
{
events: [1, 2],
name: "My name"
}
And here 1 and 2 are the IDs of events you want to add.
Late reply. Hoping this might help someone!
Right now I am using Strapi v4.3.2 and was facing the same issue. I overcame this by overriding the default core controller for create as explained in official docs. Relations are now visible!
async create(ctx) {
const { data } = ctx.request.body;
const response = await strapi.entityService.create(
"api::collection.collection",
{
data: data,
}
);
return {response}
}
This is (still? again?) a bug in Strapi, see: https://github.com/strapi/strapi/issues/12238
As a workaround you need to add the find-permission to the user / role who is performing the request for the related content type (you want to check first if this is a security issue for your scenario or not - alternatively you might want to try Paratron's approach which is described in the comments).

Recurring payments through Paypal's Express Checkout REST API

My goal is to set up recurring 6 and 12 month subscriptions using "paypal" as the payment method for our SaaS. I'm using the rest API, and the one thing I can't find is a working implementation for how to take a one time sale and re-work my code into a recurring payment using PayPal's rest API (which I've read is now possible). Here's where we are at:
I have a working advanced server integration for making payments with Paypal's Express Checkout REST API.
I created the one time sale by following the code examples as explained at the above link as well as what's shown in this example from paypal. I've tried to switch out the two step process to instead include the billing-agreement creation and execution calls, but light window that opens up to have users sign in to paypal is stopping short with the error message "Things don't appear to be working at the moment. Please try again later". Here's my javascript code, which is almost exactly the same as the working example, but with different routes.
paypal.Button.render({
// Set your environment
env: 'sandbox', // sandbox | production
// Wait for the PayPal button to be clicked
payment: function(resolve, reject) {
// Make a call to the merchant server to set up the payment
console.log("button clicked")
return paypal.request.post('/payment/paypal/subscription', {amount: '0.02'})
.then(function(res) {
resolve(res.payToken); #--WHERE I'M GOING WRONG
})
.catch(function(err) { reject(err); });
},
// Wait for the payment to be authorized by the customer
onAuthorize: function(data) {
// Make a call to the merchant server to execute the payment
return paypal.request.post('/payment/paypal/execute', {
data: data,
paymentID: data.paymentID,
payerID: data.payerID
}).then(function (res) {
if (res.state == "active") {
document.querySelector('#paypal-button-container-server').innerText = 'Payment Complete!';
} else {
console.log(res);
alert("Payment could not be approved, please try again.")
}
});
}
}, '#paypal-button-container-server');
I can tell that I'm going wrong in the payment function, namely on the line with resolve(res.payToken). I don't know what piece of data from the v1/payments/billing-agreements response I should be passing to this function, but have tried both the profile_id and the approval_url (the actual href - "href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-XXXXXXXXXXXXX").
Where am I going wrong? If this is possible, I feel like I'm one working example away from making this work, but I'd like to know if it's not capable the way I'm doing it (in which case it might need to be done via Payflow?).
Note: I fully understand billing agreements and billing profiles, and my problems are not with the REST API. In addition to the working one-time sale implementation, I can make all necessary billing profile/agreements (verified through Postman).
Below is the response from a v1/payments/billing-agreements sandbox call in the event anyone can point out the right piece of data inside of it.
{
"name": "Magazine Subscription",
"description": "Monthly subscription with a regular monthly payment definition and two-month trial payment definition.",
"plan": {
"id": "P-XXXXXXXXXXXXXXXXXXX",
"state": "ACTIVE",
"name": "1 Month Recurring",
"description": "A recurring payment plan for customers who sign a 1-month contract",
"type": "FIXED",
"payment_definitions": [
{
"id": "PD-924GIUJ3MWQ32E22348G0018",
"name": "Regular Payment Definition",
"type": "REGULAR",
"frequency": "Month",
"amount": {
"currency": "USD",
"value": "150"
},
"cycles": "1",
"charge_models": [
{
"id": "CHM-940183BIUJ3MWQ5VK14226VH",
"type": "TAX",
"amount": {
"currency": "USD",
"value": "10"
}
}
],
"frequency_interval": "1"
},
{
"id": "PD-5604RIUJ3MWQ4Y4221782C61",
"name": "Trial Payment Definition",
"type": "TRIAL",
"frequency": "Month",
"amount": {
"currency": "USD",
"value": "120"
},
"cycles": "1",
"charge_models": [
{
"id": "CHM-640401IUJ3MWQ64W07759LB2",
"type": "TAX",
"amount": {
"currency": "USD",
"value": "10"
}
}
],
"frequency_interval": "1"
}
],
"merchant_preferences": {
"setup_fee": {
"currency": "USD",
"value": "0"
},
"max_fail_attempts": "3",
"return_url": "http://localhost:8000/payment/success",
"cancel_url": "http://localhost:8000/payment/new",
"auto_bill_amount": "NO",
"initial_fail_amount_action": "CONTINUE"
}
},
"links": [
{
"href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-XXXXXXXXXXXXXX",
"rel": "approval_url",
"method": "REDIRECT"
},
{
"href": "https://api.sandbox.paypal.com/v1/payments/billing-agreements/EC-XXXXXXXXXXXXX/agreement-execute",
"rel": "execute",
"method": "POST"
}
],
"start_date": "2017-12-22T09:13:49Z"
}
The REST API's still pass back the express checkout URL's but in order to use it with the checkout.js front end integration you need to pass back the token found within the approval URL. You can either parse this URL and get the token section on the server and return it back or pass it before you call resolve method.
i.e.
approval_url = {
"href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-XXXXXXXXXXXXX"
}
var token = "EC-XXXXXXXXXXXXX";
resolve(token);

"Invalid project" error form Google API Javascript client

I am starting to play with Google Cloud DNS and I would like to hack a small Javascript project for listing/editing zones / resourceRecords.
I started on the "Getting Started" page which explains and offers some samples of the JS query/edit process. The thing is I got at some point where Google API responds with and "Invalid project" error for all supplied values of the 'project' parameter. I am using the clientID for the web application from the Google Developer Console for the oAuth part. The project name I am using is the string named PROJECT ID in google (the same one I am using successfully in the gcloud command-line tools or the on-line JS testground).
According to this: https://content.googleapis.com/discovery/v1/apis/dns/v1beta1/rpc the dns.resourceRecordsSets.list requires two parameters: managedZone and project. If I do a call without params I get this:
[
{
"error": {
"code": 400,
"message": "Required value: managedZone",
"data": [
{
"domain": "global",
"reason": "required",
"message": "Required value: managedZone"
},
{
"domain": "global",
"reason": "required",
"message": "Required value: project"
}
]
},
"id": "gapiRpc"
}
]
which is perfectly fine...
Next I add the project and the managedZone params and then I get this:
[
{
"error": {
"code": 400,
"message": "Invalid parameter: project",
"data": [
{
"domain": "global",
"reason": "invalidParameter",
"message": "Invalid parameter: project",
"locationType": "parameter",
"location": "project"
}
]
},
"id": "gapiRpc"
}
]
Here is my API call code.... I also tried checking the JS code from Google with no success in finding the "Invalid parameter" code...
gapi.client.load('dns', 'v1beta1', function() {
var request = gapi.client.dns.resourceRecordSets.list({
'project': 'lolName',
'managedZone': 'lolZone'
});
request.execute(function(resp) {
console.log(resp);
if (resp.code == 200) {
// do some displaying
}
else {
document.getElementById('content').appendChild(document.createTextNode('Error: ' + resp.message));
}
});

Categories