Call Restlet from User Event Script Error INVALID_LOGIN_ATTEMPT - javascript

I am trying to access Restlet from User Event script but i am receiving error: body":"error code: INVALID_LOGIN_ATTEMPT\nerror message: Invalid login attempt. Do i need to pass credentials too? what should i pass client id, client secret? is there another way?
I also tried url.resolveScript but no luck.
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope Public
*/
define(["N/https", "N/log", "N/record", "N/url" ],
function(https, log, record, url) {
function beforeLoad(context) {
// log.debug('beforeLoad Triggered');
// context.newRecord;
// context.type;
// context.form;
return;
}
function afterSubmit(context) {
log.debug('Before code');
var record = context.newRecord;
var requestBody = {
"recordId": record.id,
"recordType": record.type,
};
var output = url.resolveScript({
scriptId: '1157',
deploymentId: '1',
});
var output1 = 'https://12345-sb5.restlets.api.netsuite.com';
log.debug('After code', output );
var response = https.post({
url: output1 + output,
body: requestBody,
});
if (response.code === 200) {
// success!
} else {
// handle error
}
log.debug('After code', response );
return;
}
function beforeSubmit(context) {
// log.debug('beforeSubmit Triggered');
// context.newRecord;
// context.oldRecord;
// context.type;
return;
}
return {
beforeLoad : beforeLoad,
afterSubmit : afterSubmit,
beforeSubmit : beforeSubmit
}
})

Why do you need your UE Script to submit and trigger your RESTlet every record submit?
Below could work for ClientScript, just not sure if saveRecord (only when the Submit/Save is clicked) entry point will trigger this.
var requestBody = JSON.stringify({
recordId: record.id,
recordType: record.type
});
var output = url.resolveScript({
scriptId: '1157',
deploymentId: '1'
});
var response = https.post({
url: output,
body: requestBody
});
Previously you could manipulate the cookies and pass it. However, it's no longer the case and Server Scripts cannot call Server Scripts unless you pass Authentication which is a pain if you have no library. Oauth1 + SHA256 is complicated to figure out without libraries.
You could probably approach this on another angle depending on your use case. At this moment, it isn't clear why you want AfterSubmit to call RESTlet. If you do this, if you have routine Scheduled Scripts that touches that record and saves the record, it will keep triggering your AfterSubmit unless you place an if statement.

try https.requestRestlet
var response = https.requestRestlet({
body: JSON.stringify({
"recordId": record.id,
"recordType": record.type,
}),
deploymentId: '1',
method: 'POST',
scriptId: 1157,
});

Related

Having issues understanding flow - HTML form data handling by vue and axios

I am new to Vue and Axios and trying to use it in Salesforce Marketing Cloud - Cloud pages. Basically there are 3 parts,
HTML + vue page : this is a form page, where the user is asked to input the automation name and click on send button
App.js : this is build using axios and Vue.
Form-hander.js (backend) : SSJS code that runs the automation.
I referred this document to build this setup -https://ampscript.xyz/how-tos/how-to-start-status-of-automation-from-marketingcloud-form/. I understand the Form-hander.js (ssjs) code and this can be skipped.
What I am not able to understand is the flow of App.js, could anyone please explain me what is happening here.
I understand that on click of send button, the function in App.js - validateForm is called. Here after I don’t understand the flow of the code.
From App.js is the form-handler code called ? OR the post method used in the HTML page is directly called the form-handler page and staring the automation?
Here is the code of app.js. Can some explain to me in simple terms the flow of this code, would be really helpful.
new Vue({
el: '#app',
data: {
status: 100,
form: {
name: 'My Test Automation',
context: 'perform'
},
endpoint: '',
message: ''
},
watch: {
status: function () {
if(this.status == 201 || this.status == 102) {
this.form.context = 'check';
} else {
this.form.context = 'perform';
}
}
},
mounted: function() {
this.endpoint = this.$refs.form.getAttribute('action');
},
methods: {
sendFormData: function() {
this.status = 101;
var $this = this;
axios({
method: 'POST',
url: $this.endpoint,
data: $this.form,
validateStatus: function() { return true }
}).then(function(result) {
$this.status = result.data.Status;
$this.message = result.data.Message;
$this.checkStatus();
}).catch(function(error) {
console.error(error);
});
},
checkStatus: function() {
var $this = this;
var intervalID = setInterval(function() {
axios({
method: 'POST',
url: $this.endpoint,
data: $this.form,
validateStatus: function() { return true }
}).then(function(result) {
$this.status = result.data.Status;
$this.message = result.data.Message;
if($this.status == 200 || $this.status == 500) {
clearInterval(intervalID);
}
}).catch(function(error) {
console.error(error);
});
}, 10000);
},
validateForm: function() {
if (this.$refs.form.checkValidity() !== false) {
this.sendFormData();
}
this.$refs.form.classList.add('was-validated');
}
}
})
Let me explain you the flow of the code you posted :
Once component mounted, The first method which is getting called is mounted(). In this method you are fetching the endopint binded to the action attribute in your form html element and binding that in a data variable via this.endpoint.
Now, you are calling validateForm() method on click of submit button to validate the input fields. If validation pass, you are calling sendFormData() method to make an POST API call.
After getting the response, you added a watcher on status to update the form.context value based on the status code you received from an API response.
At the end, you are calling a checkStatus() method on success of axios call and in this checkStatus() method you are again making an POST API call after every 10 seconds and following step 3.
When the components is mounted, you run the form binded action on (submit?)
The action is probably binded to the sendFormData function(in methods)
Inside sendFormData, there is the setup of the axios request, followed be a then callback which handles the response from the request
The checkStatus function is called inside the "then" block
Sends the same data back to the server every 10 seconds if the previous response
doesn't have status code other than 200 or 500.
ValidateForm is may binded to some onInput or onChange event on the template
** The watcher is always looking for the status code and updates a form context

How to wait for promise to complete with returned value using angularjs

I’m having an issue with my project. In my angularjs controller a function is being executed and then my function to make a call to my database to update a record is executing without waiting for the first function to complete and therefore sending over an undefined result variable.
Below you can find my code snippets with my attempts so far.
Submit button function:
$scope.submitNewStarters = function () {
// result is returning as undefined <<<<< Issue
var result = $scope.sendNewStarterDetailsToApi();
$scope.updateArchivedImportFlag(result);
};
Controller function handling the logic:
$scope.sendNewStarterDetailsToApi = function () {
swal({
title: "Confirmation",
text: "Are you sure you want to import the new starter details?",
icon: "info",
dangerMode: true,
buttons: ["No", "Yes"]
}).then(function (approve) {
if (approve) {
// Get each of the new starter details that have been set to true for import.
var newStartsToImport = $scope.tableParams.data.filter(x => x.imported == true);
for (let i = 0; i < newStartsToImport.length; i++) {
// Parses the current new starter object into a stringified object to be sent to the api.
$scope.newStartsToImport = $scope.createApiObject(newStartsToImport[i]);
// A check to ensure that nothing has went wrong and that the stringify object has worked.
if ($scope.newStartsToImport !== "") {
apiFactory.postNewStarterDetailsToApi($scope.newStartsToImport).then(function (response) {
var isSuccessful = response.data.d.WasSuccessful;
if (isSuccessful)
toastr.success("New starter details successfully sent to API.", "Success!");
else {
var errorMessage = response.data.d.ErrorMessage;
toastr.error("New starter details were unsuccessfully sent to API. Please try again. \n" + errorMessage, "Error!");
}
});
}
else {
toastr("An error has occurred when attempting to create the data object to be sent to API. The process has stopped!", "Error!");
break;
}
}
return newStartsToImport;
}
else
toastr.info("No new starter details were sent to API", "Information!");
});
};
Factory function for API call:
postNewStarterDetailsToApi: function (data) {
return $http({
url: "https://www.example.com/services/service.svc/Import",
method: "POST",
data: data,
headers: {
'Content-Type': 'application/json; charset=utf-8',
}
}).then(function successCallbwack(response) {
// this callback will be called asynchronously
// when the response is available
return response;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('An error has occured during the function call postNewStarterDetailsToApi(): ', response);
});
}
So with the concept of promises how am I able to execute the sendNewStarterDetailsToApi function, wait for it to complete and then return the populated array? Once the populated array (result) is returned then execute the updateArchivedImportFlag function.
Below I've added an illustration of what I'd like to achieve:
The approach I am using is , save all the promises in an array .
Use any promise library or es6 Promise, and use .all function to wait for all promises to execute
The syntax i wrote is not totally correct. Since you are using angular js , you can use $q.all
$scope.sendNewStarterDetailsToApi = function () {
swal({
title: "Confirmation",
text: "Are you sure you want to import the new starter details?",
icon: "info",
dangerMode: true,
buttons: ["No", "Yes"]
}).then(function (approve) {
var res = [];
if (approve) {
// Get each of the new starter details that have been set to true for import.
var newStartsToImport = $scope.tableParams.data.filter(x => x.imported == true);
for (let i = 0; i < newStartsToImport.length; i++) {
// Parses the current new starter object into a stringified object to be sent to the api.
$scope.newStartsToImport = $scope.createApiObject(newStartsToImport[i]);
// A check to ensure that nothing has went wrong and that the stringify object has worked.
if ($scope.newStartsToImport !== "") {
res.push(apiFactory.postNewStarterDetailsToApi($scope.newStartsToImport))
}
else {
toastr("An error has occurred when attempting to create the data object to be sent to API. The process has stopped!", "Error!");
break;
}
}
return Promise.all(res);
}
else
toastr.info("No new starter details were sent to API", "Information!");
}).then(function (data) {
data.forEach((response) => {
var isSuccessful = response.data.d.WasSuccessful;
if (isSuccessful)
toastr.success("New starter details successfully sent to API.", "Success!");
else {
var errorMessage = response.data.d.ErrorMessage;
toastr.error("New starter details were unsuccessfully sent to API. Please try again. \n" + errorMessage, "Error!");
}
})
}).then((res) => {
//call Submit new starters
})
};

How to use servicebus topic sessions in azure functionapp using javascript

I have an Azure Functionapp that processes some data and pushes that data into an Azure servicebus topic.
I require sessions to be enabled on my servicebus topic subscription. I cannot seem to find a way to set the session id when using the javascript functionapp API.
Here is a modified extract from my function app:
module.exports = function (context, streamInput) {
context.bindings.outputSbMsg = [];
context.bindings.logMessage = [];
function push(response) {
let message = {
body: CrowdSourceDatum.encode(response).finish()
, customProperties: {
protoType: manifest.Type
, version: manifest.Version
, id: functionId
, rootType: manifest.RootType
}
, brokerProperties: {
SessionId: "1"
}
context.bindings.outputSbMsg.push(message);
}
.......... some magic happens here.
push(crowdSourceDatum);
context.done();
}
But the sessionId does not seem to get set at all. Any idea on how its possible to enable this?
I tested sessionid on my function, I can set the session id property of a message and view it in Service Bus explorer. Here is my sample code.
var connectionString = 'servicebus_connectionstring';
var serviceBusService = azure.createServiceBusService(connectionString);
var message = {
body: '',
customProperties:
{
messagenumber: 0
},
brokerProperties:
{
SessionId: "1"
}
};
message.body= 'This is Message #101';
serviceBusService.sendTopicMessage('testtopic', message, function(error)
{
if (error)
{
console.log(error);
}
});
Here is the test result.
Please make sure you have enabled the portioning and sessions when you created the topic and the subscription.

How to prevent current user get notified?

I'm making an app that allows user to like and comment on other user post. I'm using Parse as my backend. I'm able to notified user everytime their post liked or commented. However if current user like or comment on their own post this current user still notified. How can I prevent this?
Here is the js code that I use:
Parse.Cloud.afterSave('Likes', function(request) {
// read pointer async
request.object.get("likedPost").fetch().then(function(like){
// 'post' is the commentedPost object here
var liker = like.get('createdBy');
// proceed with the rest of your code - unchanged
var query = new Parse.Query(Parse.Installation);
query.equalTo('jooveUser', liker);
Parse.Push.send({
where: query, // Set our Installation query.
data: {
alert: message = request.user.get('username') + ' liked your post',
badge: "Increment",
sound: "facebook_pop.mp3",
t : "l",
lid : request.object.id,
pid: request.object.get('likedPostId'),
lu : request.user.get('username'),
ca : request.object.createdAt,
pf : request.user.get('profilePicture')
}
}, {
success: function() {
console.log("push sent")
},
error: function(err) {
console.log("push not sent");
}
});
});
});
If I understand the context of where this code is correctly,
I recommend checking
if request.user.get("username") != Parse.CurrentUser.get("username")
Before sending out the push notification
Where is your cloud function being called from? If you're calling it from your ios code, then before you call the cloud code function, just prelude it with something like this:
if (PFUser.currentUser?.valueForKey("userName") as! String) != (parseUser.valueForKey("userName") as! String)

AngularJS $resource 'GET' accesses the correct API, but 'PUT' and 'POST' do not

Follow up from AngularJS $resource calls the wrong API URL when using method:POST
My controller is set up like this, with Angular's $resource:
$scope.updateProduct = $resource('/api/updateProduct/:product/:param/:value',{},{
query: {method:'GET'},
post: {method:'POST'},
save: {method:'PUT', params: {brand: '#brand', param:'#param', value:'#value'}},
remove: {method:'DELETE'}
});
$scope.updateProduct.save({
product : $scope.post._id,
param: 'likes',
value: $scope.user._id
});
My server runs on NodeJS and ExpressJS. In my console, when the save operation is called, I can see:
POST /api/updateBrand/<productid>/likes/fun,%20quirky%20loud,%20boho,%20hippy 200 22ms - 2.31kb
However, my API is not being correctly accessed. For instance, if I go to the above URL in my browser, the API function is called, and my database is updated (and it is reported in my server's console). Yet when Angular does a PUT on this URL, nothing happens at all.
Interestingly, when I change $scope.updateProduct.save() to $scope.updateProduct.get(), the API is correctly called and everything works fine.
Any ideas what's going on here?
EDIT: Here's the server setup:
ExpressJS API setup:
app.get('/api/updateProduct/:product/:param/:value', api.updateProduct);
API code
exports.updateProduct = function (req, res) {
console.log("TEST")
var product = req.params.product;
var param = req.params.param;
var value = req.params.value;
var props = { $push: {} };
if(param == 'userTags'){
var oldVal = value;
value = oldVal.match(/[-'"\w]+/g);
props.$push[param];
props.$push[param] = {$each: []};
props.$push[param].$each = value;
}else{
var props = { $push: {} };
props.$push[param] = value;
}
db.products.update({"_id": ObjectId(product)}, props, function (err, record) {
if (err || !(record)) {
console.log("Lookup Error: " + err);
} else{
console.log("Updated " + product + " with " + param);
console.log(record);
res.json({obj:record})
}
});
};
It seems that your server is not waiting for a POST or PUT request, but a GET request as per your configuration.
app.get('/api/updateProduct/:product/:param/:value', api.updateProduct);
According to the ExpressJS API (http://expressjs.com/api.html), you should be able to replace the get with any valid http verb.
app.VERB(path, [callback...], callback)
app.post('/api/updateProduct/:product/:param/:value', api.updateProduct);
app.put('/api/updateProduct/:product/:param/:value', api.updateProduct);

Categories

Resources