Invoke Business Rules service from Node js application on Bluemix - ibm-cloud

I have my ruleset deployed on the Business Rules service on Bluemix.
How do I invoke the rules using API from my Node js application on Bluemix?

After binding the Business Rules service instance to the application, rules can be invoked using the invokeRulesService method defined as follows:
// Check for Business Rules service
var brules = null;
//parse VCAP_SERVICES if running in Bluemix
if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
console.log(env);
//find the Business Rules service
if (env["businessrules"])
{
brules = env['businessrules'][0]['credentials'];
console.log(brules);
}
else
{
console.log('Please bind the Business Rules service to this application');
}
}
function invokeRulesService(rulesetPath, inputParams, callback) {
// check if brules is null
if (brules == null){
console.log("Please bind the business rules service to this application.");
return;
}
var restUrl = url.parse(brules.executionRestUrl);
var dataString = JSON.stringify(inputParams);
// encode 'user:password' in Base64 string for basic authentication of the execution API
var encodedCredentials = new Buffer(brules.user+':'+brules.password).toString('base64');
headers = { 'Content-Type': 'application/json',
'Content-Length': dataString.length,
'Authorization': 'Basic ' + encodedCredentials // basic authentication header
};
var options = {
host: restUrl.host,
path: restUrl.path + rulesetPath,
method: 'POST',
headers: headers
};
var req = https.request(options, function(resp) {
resp.setEncoding('utf-8');
var responseString = '';
resp.on('data', function(data) {
responseString += data;
});
resp.on('end', function() {
console.log(responseString);
if (resp.statusCode == 200)
var responseObject = JSON.parse(responseString);
callback(responseObject);
});
});
req.on('error', function(e) {
console.log(e.message);
});
req.write(dataString);
req.end();
}

Related

Sharepoint list item using Api Rest

I need to get a list's items, so I created this function
export function retrieveSPItems(spToken, alias) {
var url = `{path_to_my_site}/_api/web/Lists/getByTitle('Briefs')/ItemCount`;
var myHeaders = new Headers({
Accept: "application/json;odata=nometadata",
Authorization: spToken,
});
return fetch(url, {
method: "get",
headers: myHeaders,
}).then((response) => response.json());
}
As a output I get 3000.
when I change the url to
var url = `{path_to_my_site}/_api/web/Lists/getByTitle('Briefs')/Items`;
I get an empty list!
PS :
It's work in Postman with no problem
The token is generated by adaljs :
Get Token
authContext.acquireToken(SP_BASE_URL, function (error, token){....})
Adal config
export const adalConfig = {
tenant: CURRENT_TENANT,
clientId: CURRENT_APP_ID,
endpoints: {
api: CURRENT_APP_ID,
graph: GRAPH_BASE_URL,
sharepoint: SP_BASE_URL,
},
cacheLocation: "localStorage",
validateAuthority: true,
};
So I need to know :
what the reason fot this issue?
How can I fix it?
It's too general information, you need debug and figure out the detailed error information.
My test demo:
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="Scripts/adal.js"></script>
<script type="text/javascript">
var authContext = null;
var user = null;
(function () {
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: 'xxx.onmicrosoft.com',
clientId: '9afc37cb-x-x-x-xxx',
postLogoutRedirectUri: window.location.origin,
endpoints: {
graphApiUri: "https://graph.microsoft.com",
sharePointUri: "https://xxx.sharepoint.com/",
},
cacheLocation: 'localStorage' // enable this for IE, as sessionStorage does not work for localhost.
};
authContext = new AuthenticationContext(config);
var isCallback = authContext.isCallback(window.location.hash);
authContext.handleWindowCallback();
//$errorMessage.html(authContext.getLoginError());
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
}
user = authContext.getCachedUser();
if (!user) {
authContext.login();
}
//authContext.acquireToken(window.config.clientId, function (error, token) {
// console.log('---');
//})
authContext.acquireToken(window.config.endpoints.sharePointUri, function (error, token) {
alert(token);
if (error || !token) {
console.log("ADAL error occurred: " + error);
return;
}
else {
var listUri = window.config.endpoints.sharePointUri + "sites/lee/_api/web/lists/GetByTitle('mylist')/items?$select=Title";
$.ajax({
type: "GET",
url: listUri,
headers: {
"Authorization": "Bearer " + token,
"accept": "application/json;odata=verbose"
}
}).done(function (response) {
console.log("Successfully fetched list from SharePoint.");
var items = response.d.results;
for (var i = 0; i < items.length; i++) {
console.log(items[i].Title);
$("#SharePoint").append("<li>" + items[i].Title + "</li>");
}
}).fail(function () {
console.log("Fetching list from SharePoint failed.");
})
}
})
}());
</script>

Passport-jwt issue : JWT token is working with postman but not working with UI api call

I have integrated passport-jwt for authentication purpose. It's working like charm but whenever Frontend guy use it from frontend angular 2 its giving Unauthorised 401 . I've tried alot but not getting any clue, it must be a silly mistake though.
my passport strategy file is as
let JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
//let fromHeader = require('passport-jwt').fromHeader
// load up the user model
const User = require('../components/user/model');
const database = require('./database'); // get db config file
const config = require('./config'); // get db config file
module.exports = function(passport) {
//var passportStrategy = function(passport){
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
//opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("JWT");
console.log("opts.jwtFromRequest==",opts.jwtFromRequest);
opts.secretOrKey = config.secret;//config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
//console.log("opt==",JSON.stringify(opt));
//console.log("jwt_payload===",jwt_payload);
User.findOne({_id: jwt_payload._doc._id}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
}
});
}));
};
my route is as
app.get("/api/user/getAll",
passport.authenticate('jwt',{session:false}),
userController.fetchUsers
);
And frontend header append is as follows :
logoutUser(token) {
//const userData = JSON.stringify(userInfo);
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', token); //e.g.token = JWT dasddddasdsda
//headers.append('Authentication', token);
console.log(headers)
return this.http.post('http://localhost:9000/api/user/logout', { headers: headers })
.map((response: Response) =〉 {
return response.json()
})
.catch(this.errorHandler);
}
It would really great if anyone can assist me further to identify the mistake.
Second argument for the post method is payload.
so this code below
this.http.post('http://localhost:9000/api/user/logout', { headers: headers })
has to be
this.http.post('http://localhost:9000/api/user/logout', {}, { headers: headers })

API Gateway Custom Authorizer for Federated Identity

I created a custom authorizer for API Gateway so that i can pass the Facebook token and it will authenticate it using Cognito's Federated identity.
My problem is that the fb token seems to expire so I keep getting 403 errors. I am wondering if my approach is correct. Should I pass the Facebook token as part of the request header to API gateway on every REST API call or so I pass AWS identity id instead. Any feedback is appreciated. Thank you.
var AWS = require('aws-sdk');
var cognitoidentity = new AWS.CognitoIdentity();
exports.handler = (event, context, callback) => {
var params = {
IdentityPoolId: 'us-west-2:xxxxxxxxxxxxxxxxx’, /* required */
AccountId: ‘xxxxxxxxxxxxxxxxx,
Logins: {
'graph.facebook.com': event.authorizationToken //Token given by Facebook
}
};
console.log(event.methodArn);
cognitoidentity.getId(params, function(err, data) {
if (err) {
console.log(err);
callback(null, generatePolicy('user', 'Deny', event.methodArn));
}
else{
console.log("success");
callback(null, generatePolicy('user', 'Allow', event.methodArn));
}
});
};
var generatePolicy = function(principalId, effect, resource) {
var authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke'; // default action
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
}

How to make restapi call from jasmine-protractor for non-angular app

I am using jasmine-protractor e2e framework to test one of our desktop App. I am totally new to this. So if something is not clear please ask.
This is how I am logging in to the server. Server uses SSO for authentication
describe('Protractor', function() {
beforeEach(function() {
browser.ignoreSynchronization = true
browser.get('https://myserver.com/login.html',60000);
});
it('hi', function () {
var btn = element(by.css('.loginFormGroup')).element(by.partialLinkText('Tegile'));
btn.click();
// browser.ignoreSynchronization = false;
var user = element(by.css('.UsernamePasswordTable')).element(By.id('ctl00_ContentPlaceHolder1_UsernameTextBox'));
user.sendKeys('user');
var pass = element(by.css('.UsernamePasswordTable')).element(By.id('ctl00_ContentPlaceHolder1_PasswordTextBox'));
pass.sendKeys('passwd');
var SignIn = element(by.css('.UsernamePasswordTable')).element(By.id('ctl00_ContentPlaceHolder1_SubmitButton'));
// browser.pause();
SignIn.click();
});
After this i would like to execute restapi on the same server. I want it to use same session if possible.
I tried to use request/request, but didnt work. Maybe i was not using it correctly.
You can simply use nodejs http module to make API calls.Look at below examples on how to make both GET and POST calls using http module.
GET call:
var http = require('http');
var headerObj = { Cookie : 'cookie-value' }
var options = {
host: "localhost" ,
path: "/someurl",
port: 8080,
headers : headerObj
};
var req= http.request(options,function(response) {
var body = '';
response.on('data', function(d) {
body += d;
});
response.on('end', function() {
console.log(body);
});
}).on('error', function (err) {
console.log(err);
});
req.end();
POST call:
var http = require('http');
var data = { name : "somename" }; //data that need to be posted.
var options = {
"method": "POST",
"hostname": "localhost",
"port": 8080,
"path": "/someurl",
"headers": {
"content-type": "application/json",
"cache-control": "no-cache",
cookie: 'cookie-value'
}
};
var req = http.request(options, function (res) {
var body = '';
res.on("data", function (chunk) {
body = body + chunk;
});
res.on("end", function () {
console.log(body);
});
});
req.write(JSON.stringify(data));
req.end();
I used SuperAgent to make REST API calls for my application,
below is the link describes the usage of superagent.
npm package superagent

Using QUnit and sinon.spy, how can I access my spy within an async callback?

I am new to QUnit and sinon.js and working to build tests for an ember-cli package. I am having problems getting sinon.spy(Ember.run, 'later') to work with the code below. inside the callback Ember.run.later is not being spied / has no .getCalls() etc...
How can I handle this type of test?
test('#authenticate rejects with invalid credentials', function() {
sinon.spy(Ember.run, 'later');
var jwt = JWT.create(),
expiresAt = (new Date()).getTime() + 60000;
var token = {};
token[jwt.identificationField] = 'test#test.com';
token[jwt.tokenExpireName] = expiresAt;
token = window.btoa(JSON.stringify(token));
var credentials = {
identification: 'username',
password: 'password'
};
App.server.respondWith('POST', jwt.serverTokenEndpoint, [
400,
{
'Content-Type': 'application/json'
},
'{"message":["Unable to login with provided credentials."]}'
]);
Ember.run(function(){
App.authenticator.authenticate(credentials).then(null, function(){
// Check that Ember.run.later was not called.
equal(Ember.run.later.getCall(0), null);
});
});
Ember.run.later.restore();
});
PS I currently am able to get this working by moving the sinon.spy and corresponding Ember.run.later.restore() to the module.setup() and module.teardown() methods respectively. Is there anything wrong with that that strategy other than it means they are spied for every test in my suite?
Thanks!
EDIT: Here is my authenticate method:
authenticate: function(credentials) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
var data = _this.getAuthenticateData(credentials);
_this.makeRequest(_this.serverTokenEndpoint, data).then(function(response) {
Ember.run(function() {
var tokenData = _this.getTokenData(response),
expiresAt = tokenData[_this.tokenExpireName];
_this.scheduleAccessTokenRefresh(expiresAt, response.token);
response = Ember.merge(response, { expiresAt: expiresAt });
resolve(_this.getResponseData(response));
});
}, function(xhr) {
Ember.run(function() {
reject(xhr.responseJSON || xhr.responseText);
});
});
});
},