Getting a 403 Forbidden error on plugin request - filenet-p8

I'm trying to fire a plugin request from my ICN plugin. The request goes as below. However, I'm getting a 403 Forbidden error from the server.
Forbidden
You don't have permission to access /navigator/jaxrs/plugin on this server.
https://<icnserver.com>/navigator/jaxrs/plugin?repositoryId=Demo&query=%5B%7B%22name%22%3A%22ID%22%2C%22operator%22%3A%22LIKE%22%2C%22values%22%3A%5B%22123434234%22%2C%22%22%5D%7D%5D&className=Checks&plugin=DemoPlugin&action=DemoService&desktop=Demo
Plugin JS:
aspect.around(ecm.model.SearchTemplate.prototype, "_searchCompleted", function advisingFunction(original_searchCompleted){
return function(response, callback, teamspace){
var args = [];
var templateName = response.templates[0].template_name;
var res = response;
var requestParams = {};
requestParams.repositoryId = this.repository.id;
requestParams.query = query;
requestParams.className = templateName;
Request.invokePluginService("DemoPlugin", "DemoService",
{
requestParams: requestParams,
requestCompleteCallback: lang.hitch(this, function(resp) { // success
res.rows = resp.rows;
res.num_results = resp.rows.length;
res.totalCount = resp.rows.length;
args.push(res);
args.push(callback);
args.push(teamspace);
original_searchCompleted.apply(this,args);
})
}
);
}
});

You need to provide a security_token to be able to call your service, so you need to login first.
Then, open your browser's debug and check the requests in the network tab.
There you can see that every request that targets the /navigator/jaxrs/* URI will contain it, so something like this will be among the headers:
security_token: 163594541620199174
So my bet is that you have not set it in your client (I recommend a postman to test your service, or I would add a test (ICN) feature page in the ICN plugin project in order to be able to call it properly). In your feature page, you can call your service directly using the ecm/model/Request OOTB navigator dojo/javascript class, as you can see in CheckinAction.js:
_checkInDocument: function (item, requestData)
{
var self = this;
var payLoadObject = {requestType: "Get", id: item.id};
Request.postPluginService("DocuSignPlugin", "UpdateSignedDocumentService", "application/json", {
requestParams: {
repositoryId : item.repository.id,
serverType : item.repository.type,
docId : item.docid,
envelopeId: item.attributes.DSEnvelopeID,
payLoad: json.stringify(payLoadObject)
},
requestCompleteCallback: function(response) {
if (response.returncode == 0)
{
item.attributeDisplayValues.DSSignatureStatus = "Checkedin";
item.attributes.DSSignatureStatus = 4;
item.update(item);
}
else if (response.returncode == -1)
{
items = [];
items.push(item);
self._showLoginDialog(items);
}
},
backgroundRequest : false,
requestFailedCallback: function(errorResponse) {
// ignore handline failures
}
});
},
As you can see, you don't have to add the security_token to the requestParams, the framework will do it for you.

Related

Bad request error from UrlFetchApp when fetching the API url

I am getting the following error message: Bad request: [URL] when fetching the API URL using UrlFetchApp.
I need to pass the access token which has been received from the authorization server using a GET request.
My code is:-
function run()
{
var service = getOAuthService();
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s',
authorizationUrl);
Logger.log(JSON.stringify(service.getAccessToken(), null, 2));
if (service.hasAccess()) {
var url = 'https://ffa-int-service-lnhtqfum-zgvbwhku.apps.dev.aro.forgeapp.honeywell.com/get_graph_data';
var options =
{
method: 'GET',
headers: {
'Authorization' : 'Bearer ' + service.getAccessToken(),
},
muteHttpExceptions : true,
followRedirects: true
};
var response = UrlFetchApp.fetch(url,options);
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s',
authorizationUrl);
}
}

Is there a way to show "Loading data.." option in Rally Grid(ext JS) while making the Ajax request to load the data?

I am trying to set the message to "Data Loading.." whenever the data is loading in the grid. It is working fine if I don't make an Ajax call. But, when I try to make Ajax Request, It is not showing up the message "Loading data..", when it is taking time to load the data. Can someone please try to help me with this.. Thanks in Advance.
_loadData: function(x){
var that = this;
if(this.project!=undefined) {
this.setLoading("Loading data..");
this.projectObjectID = this.project.value.split("/project/");
var that = this;
this._ajaxCall().then( function(content) {
console.log("assigned then:",content,this.pendingProjects, content.data);
that._createGrid(content);
})
}
},
_ajaxCall: function(){
var deferred = Ext.create('Deft.Deferred');
console.log("the project object ID is:",this.projectObjectID[1]);
var that = this;
console.log("User Reference:",that.userref,this.curLen);
var userObjID = that.userref.split("/user/");
Ext.Ajax.request({
url: 'https://rally1.rallydev.com/slm/webservice/v2.0/project/'+this.projectObjectID[1]+'/projectusers?fetch=true&start=1&pagesize=2000',
method: 'GET',
async: false,
headers:
{
'Content-Type': 'application/json'
},
success: function (response) {
console.log("entered the response:",response);
var jsonData = Ext.decode(response.responseText);
console.log("jsonData:",jsonData);
var blankdata = '';
var resultMessage = jsonData.QueryResult.Results;
console.log("entered the response:",resultMessage.length);
this.CurrentLength = resultMessage.length;
this.testCaseStore = Ext.create('Rally.data.custom.Store', {
data:resultMessage
});
this.pendingProjects = resultMessage.length
console.log("this testcase store:",resultMessage);
_.each(resultMessage, function (data) {
var objID = data.ObjectID;
var column1 = data.Permission;
console.log("this result message:",column1);
if(userObjID[1]==objID) {
console.log("obj id 1 is:",objID);
console.log("User Reference 2:",userObjID[1]);
if (data.Permission != 'Editor') {
deferred.resolve(this.testCaseStore);
}else{
this.testCaseStore = Ext.create('Rally.data.custom.Store', {
data:blankdata
});
deferred.resolve(this.testCaseStore);
}
}
},this)
},
failure: function (response) {
deferred.reject(response.status);
Ext.Msg.alert('Status', 'Request Failed.');
}
});
return deferred;
},
The main issue comes from your Ajax request which is using
async:false
This is blocking the javascript (unique) thread.
Consider removing it if possible. Note that there is no guarantee XMLHttpRequest synchronous requests will be supported in the future.
You'll also have to add in your success and failure callbacks:
that.setLoading(false);

Ext.data.Connection.override request

I am trying to intercept all requests, before send, from an Extjs App, POST and GET and then manipulate the URL and add a new Header, Authorization: Bearer XYZ123.
I've this code:
Ext.data.Connection.override({
request: function (options) {
var me = this;
this.cors = true;
this.useDefaultHeader = false;
this.useDefaultXhrHeader = false;
options.headers = { "Authorization": "Bearer VAROIS1iOiJKV1QiLCJh" };
var separator = options.url.indexOf('/') == 0 ? "" : "/";
options.url = UrlAPIPrefix + separator + options.url;
return me.callOverridden(arguments);
}
});
But when i try to use it, the Header Authorization is not sent in both cases, GET and POST. Parameters are not sent when using POST. I am able to see params if debugging the code into Extjs files, but can't see it on chrome Request Headers, see image.
If any one knows how to do it, in one place, i will be glad if you can help me.
That's because Ext.Ajax - the singleton of Ext.data.Connection - is used for most requests in the framework and overriding the latter does not affect the former. This overriding behavior was changed in extjs 5 and is intended by Sencha.
Use what you need of this instead:
Ext.Ajax.setWithCredentials(true);
Ext.Ajax.on({
beforerequest: function(conn, options) {
options.headers = options.headers || {};
options.headers['Authorization'] = 'Bearer VAROIS1iOiJKV1QiLCJh';
},
requestexception: function(conn, response, options) {
Ext.Error.raise('...');
}
});
And don't hardcode the token into your javascript!!!
Instead of overriding the class, i created a bootstrap class to set up the ajax interceptor. Called Bootstrap.init() in Application.launch() method.
Ext.define('MyApp.Bootstrap', {
singleton : true,
init: function() {
Ext.Ajax.on({
beforerequest: function(conn, opts){
if(opts.url && Ext.String.startsWith(opts.url, '/')) {
return;
}
if(opts.url && !Ext.String.startsWith(opts.url, MyApp.Config.SERVER_CONTEXT)) {
opts.url = MyApp.Config.SERVER_CONTEXT + opts.url;
}
var clientId = MyApp.getApplication().clientId;
opts.headers = Ext.apply({'X-Client-Id': clientId}, opts.headers);
Ext.log('Sending Request to : ', opts.url);
}
});
}
});

React/Redux download file

I need to download a file from the server when a button is clicked.
I created a MaterialUI button and on its onclick callback i call an action of the container component connected.
The action is asynchronous and does an ajax POST:
export const onXlsxClick = () => dispatch => {
const urlParams = {
filters: {
aggregation: 'macro_area',
chart_resolution: '1_hour',
chart_from: '1478080363',
chart_to: '1477993963'
},
labels: ['PROVA1', 'PROVA2'],
series: [
{
label: null,
timestamp: 1478080363,
values: [123, 345]
},
{
label: null,
timestamp: 1477993963,
values: [153, 3435]
}
]
};
return $.ajax({
url:'/rest/export/chart/xlsx',
type: 'POST',
dataType: 'application/json',
contentType: 'application/json',
data: JSON.stringify(urlParams)
})
.done(data => {
console.log('success');
})
.fail(error => {
console.log(error);
});
};
The server receive the request and handle it correctly through this REST service:
#POST
#Path("xlsx")
#Produces("application/vnd.ms-excel")
public Response getXlsx(ChartExportRequest request) {
ResponseBuilder responseBuilder;
ChartExportRequestDTO reqDto = null;
try {
reqDto = parseDTO(request);
checkRequestDTO(reqDto);
ExportDTO dto = getXlsxProvider().create(reqDto);
responseBuilder = Response.ok(dto.getFile())
.header("Content-disposition", "attachment;filename=" + dto.getFileName());
}
catch(Exception e) {
logger.error("Error providing export xlsx for tab RIGEDI with request [" + (reqDto != null ? reqDto.toString() : null) + "]", e);
responseBuilder = Response.serverError().entity(e.getMessage());
}
return responseBuilder.build();
}
The problem is that the response arrives correctly to the client but then nothing happens: I am expecting that the browser shows the download dialog (example: in chrome I expect the bottom bar of downloads to appear with my file).
What am I doing wrong?
AS per Nate's answer here, the response of Ajax request is not recognised by a browser as a file. It will behave in the same way for all Ajax responses.
You need to trigger the download popup manually.
In my implementation, I used filesaverjs to trigger the download popup, once I have received the API response in reducer.
Since FileSaver uses blob for saving the file, I am sending the response from server as a blob, converting it into string array buffer and then using it to save my file. This approach was described in
Please find the sample code below for the reducer :
(using reducer for state modification, as per Redux)
reducer.js
let fileSaver = require("file-saver");
export default function projectReducer(state = {}, action)
{
let project;
switch (action.type) {
case GET_PROJECT_SUCCESS :
project = Object.assign(action.response.data);
return project;
case EXPORT_AND_DOWNLOAD_DATA_SUCCESS :
let data = s2ab(action.response.data);
fileSaver.saveAs(new Blob([data], {type: "application/octet-stream"}), "test.xlsx");
return state;
}
return state;
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}

Parse Response Variable Issues with HTTP Request and Cloud Code

I am trying to run an HTTP Request in an afterSave. It executes correctly, but im getting errors with the response variable I was told to put in the end.
Here is the code
Parse.Cloud.afterSave("ArtPiece", function(request) {
var artistURL = 'http://www.gallery-admin-dev.iartview.com/Gilmans/imageSave.php';
var artPiece = request.object;
if (typeof request.image === "undefined") {
var pieceName = artPiece.get("piece_name");
var url = artPiece.get("imageURL");
Parse.Cloud.httpRequest({
url: artistURL,
params: {
pieceName : pieceName,
url : url
},
success: function(httpResponse) {
response.success();
},
error: function(httpResponse) {
response.error('Request failed with response code ' + httpResponse.status)
}
});
}
});
The problem is the success and error functions.
Things I have tried that have not worked:
Putting response as a second parameter in the afterSave Call (it says can not call .success of an undefined variable)
Getting rid of the response lines of code (Result: success/error was not called)
Calling Response as its own function response('Request failed with response code ' + httpResponse.status) it just says response is undefined.
I dont really care about having any response or not, I just want the code to work properly.
How is this 'response' variable supposed to be set up?
Thank you!
There was an extra url in the parameters, a reference to a probably undefined artistURL...
Parse.Cloud.afterSave("ArtPiece", function(request) {
var artistURL = 'http://www.gallery-admin-dev.iartview.com/Gilmans/imageSave.php';
var artPiece = request.object;
if (typeof request.image === "undefined") {
var pieceName = artPiece.get("piece_name");
var url = artPiece.get("imageURL");
var params = { pieceName : pieceName };
return Parse.Cloud.httpRequest({ url: artistURL, params: params });
}
});

Resources