Following the syntax proposed on the Neo4j REST API transactional page, I have tried running the request "CREATE (node:{group} { name: {name}}) RETURN node", { group: "Group", name: "Name"}.
The use of :{group} as a dynamic variable causes an error:
"Neo.ClientError.Statement.InvalidSyntax","message":"Invalid input '{': expected whitespace or a label name
Is this pilot error on my part, a bug in the Neo4j query parser, or a something that cannot be done?
Here's my Nodej.s code:
var request = require("request")
var host = 'localhost'
, port = 7474
, user = "neo4j"
, pass = "1234"
var uri = 'http://' + user + ":" + pass + "#" + host + ':' + port + '/db/data/transaction/commit'
function runCypherQuery(query, params, callback) {
request.post({
uri: uri,
json: {statements: [{statement: query, parameters: params}]}
},
function (err, res, body) {
callback(err, body)
})
}
runCypherQuery(
"CREATE (node:{group} { name: {name}}) RETURN node"
, { group: "Group"
, name: "Name"
}
, function (err, resp) {
if (err) {
console.log(err)
} else {
console.log(JSON.stringify(resp))
}
}
)
Node Labels cannot be parameterized in Cypher.
Try updating the label in the query as a string instead of passing a parameter:
"CREATE (node:" + group + " {name: {name}}) RETURN node"
Unfortunately, Cypher does not support parameterized label names.
Related
I'm using the following iq message to create persistent rooms in openfire:
var configiq = $iq({
to : chatObj.getActiveChatRoomName() + "#" + chatObj.groupChatService,
type : "set"
}).c("x", {
xmlns : "jabber:x:data",
type : "submit"
}).c('field', {
"var" : "FORM_TYPE"
})
.c('value').t("http://jabber.org/protocol/muc#roomconfig")
.up().up()
.c('field', {
"var" : "muc#roomconfig_persistentroom"
})
.c('value').t("1");
chatObj.connection.sendIQ(configiq.tree(), function () {
console.log('success');
}, function (err) {
console.log('error', err);
});
But, I am getting the following error:
error <iq xmlns="jabber:client" type="error" id="1356:sendIQ" from="msrtc0711#conference.stslp239" to="ashishjmeshram#stslp239/ax8nb2atg1"><x xmlns="jabber:x:data" type="submit">…</x><error code="400" type="modify"><bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"></bad-request></error></iq>
Using the Strophe.muc plugin is easier:
1) firstly join the room (this creates an instant room):
connection.muc.join(room_jid, nick);
2) then create a "configured room", eventually with a subject and a description associated:
var config = {"muc#roomconfig_publicroom": "1", "muc#roomconfig_persistentroom": "1"};
if (descr) config["muc#roomconfig_roomdesc"] = descr;
if (subject) config["muc#roomconfig_subject"] = subject;
connection.muc.createConfiguredRoom(room_jid, config, onCreateRoomSuccess, onCreateRoomError);
A working example is available here: http://plnkr.co/edit/Mbi15HDZ2yW5vXskS2X6?p=preview
I am trying to create a document in the SAP Document Center of HCP using Javascript and I can not. SAP Document Center uses the CMIS protocol for communication with other applications. I have been able to connect from my SAPUI5 application with the SAP Document Center. I have also managed to create a folder as follows:
createFolder: function(repositoryId, parentFolderId, folderName) {
var data = {
objectId: parentFolderId,
cmisaction: "createFolder",
"propertyId[0]": "cmis:name",
"propertyValue[0]": folderName,
"propertyId[1]": "cmis:objectTypeId",
"propertyValue[1]": "cmis:folder"
};
$.ajax("/destination/document/mcm/json/" + repositoryId + "/root", {
type: "POST",
data: data
}).done(function() {
MessageBox.show("Folder with name " + folderName + " successfully created.");
}).fail(function(jqXHR) {
MessageBox.show("Creation of folder with name " + folderName + " failed. XHR response message: " + jqXHR.responseJSON.message);
});
},
However, I find it impossible to create a document. I can not find an internet sample for the CMIS "createDocument" method. There are many examples for Java but nothing to do with Javascript. I do not know what the structure of the data to send. The code is as follows:
createDocument: function(repositoryId, parentFolderId, documentName, content) {
/**
* 'content' contains the whole document converted to a base64 string like this:
* "data:application/pdf;base64,JVBERi0xLjUNJeLjz9MNCjIxNCAwIG9iag08P..."
*/
var data = {
objectId: parentFolderId,
cmisaction: "createDocument",
contentStream: content,
"propertyId[0]": "cmis:name",
"propertyValue[0]": documentName,
"propertyId[1]": "cmis:objectTypeId",
"propertyValue[1]": "cmis:document"
};
$.ajax("/destination/document/mcm/json/" + repositoryId + "/root", {
type: "POST",
data: data
}).done(function() {
MessageBox.show("Document with name " + documentName + " successfully created.");
}).fail(function(jqXHR) {
MessageBox.show("Creation of document with name " + documentName + " failed. XHR response message: " + jqXHR.responseJSON.message);
});
},
With this I create a file record within the SAP Document Center but it does not take the data. An unformatted file is created, when it should have the format sent (PDF, txt, Excel, Doc, ...).
Does anyone know how to do it?
Regards.
Links of interest:
CMIS Standard
http://docs.oasis-open.org/cmis/CMIS/v1.1/os/CMIS-v1.1-os.html#x1-1710002
Usage examples for Java (not Javascript)
http://chemistry.apache.org/java/developing/guide.html
I have been through a similar problem. My solution is to change it from base64 to a FormData approach, so I got the file input value instead of the content base64 string. It worked fine.
this.createObject = function (fileInput, objectName,folderId, cbOk, cbError) {
if (!folderId) {
folderId = _this.metadata.rootFolderId;
}
var documentData = {
'propertyId[1]': 'cmis:objectTypeId',
'propertyValue[1]': 'cmis:document',
'propertyId[0]': 'cmis:name',
'propertyValue[0]': objectName,
'objectId': folderId,
'cmisaction': 'createDocument',
'content' : fileInput
};
var formData = new FormData();
jQuery.each(documentData, function(key, value){
formData.append(key, value);
});
$.ajax({
url: _this.metadata.actionsUrl,
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
cbOk(data);
},
error: function(err){
cbError(err);
}
});
};
In the view.xml add following lines.
<FileUploader id="fileUploader"
name="myFileUpload"
uploadUrl="/cmis/root"
width="400px"
tooltip="Upload your file to the local server"
uploadComplete="handleUploadComplete"
change='onChangeDoc'/>
the upload url will be url to the neo destination. In the neo.app.json add the following lines.
{
"path": "/cmis",
"target": {
"type": "destination",
"name": "documentservice"
},
"description": "documentservice"
}
In the controller.js add the following lines of code.
if (!oFileUploader.getValue()) {
sap.m.MessageToast.show("Choose a file first");
return;
}
var data = {
'propertyId[0]': 'cmis:objectTypeId',
'propertyValue[0]': 'cmis:document',
'propertyId[1]': 'cmis:name',
'propertyValue[1]': file.name,
'cmisaction': 'createDocument'
};
var formData = new FormData();
formData.append('datafile', new Blob([file]));
jQuery.each(data, function(key, value) {
formData.append(key, value);
});
$.ajax('/cmis/root', {
type: 'POST',
data: formData,
cache: false,
processData: false,
contentType: false,
success: function(response) {
sap.m.MessageToast.show("File Uploaded Successfully");
}.bind(this),
error: function(error) {
sap.m.MessageBox.error("File Uploaded Unsuccessfully. Save is not possible. " + error.responseJSON.message);
}
});
In the neo cloud, maintain the url for following configuration in destination tab. https://testdaasi328160trial.hanatrial.ondemand.com/TestDaaS/cmis/json/repo-id
repo-id will be your repository key.
this will solve the problem. You will be able to upload and the document.
I'm trying to add a users identity to a channel using the REST API using instructions here: https://www.twilio.com/docs/api/ip-messaging/rest/members#action-create
I'm posting to the /Channels/channelId/Members endpoint - I'm certain my request is structured correctly.
I get an error back from Twilio IP Messaging saying:
{"code": 50200, "message": "User not found", "more_info": "https://www.twilio.com/docs/errors/50200", "status": 400}
My understanding was that we can provide our own identity when we want to add someone to a Channel. How can I 'register' the user (with an email) before adding them to the Channel?
EDIT - The code:
var _getRequestBaseUrl = function() {
return 'https://' +
process.env.TWILIO_ACCOUNT_SID + ':' +
process.env.TWILIO_AUTH_TOKEN + '#' +
TWILIO_BASE + 'Services/' +
process.env.TWILIO_IPM_SERVICE_SID + '/';
};
var addMemberToChannel = function(memberIdentity, channelId) {
var options = {
url: _getRequestBaseUrl() + 'Channels/' + channelId + '/Members',
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
form: {
Identity: memberIdentity,
},
};
request(options, function(error, response, body) {
if (error) {
// Getting the error here
}
// do stuff with response.
});
};
addMemberToChannel('test1#example.com', <validChannelId>);
Twilio developer evangelist here.
In order to add a user to be a member of a channel, you do indeed need to register them first. Check out the documentation for creating a user in IP Messaging.
With your code you'd need a function like:
var createUser = function(memberIdentity) {
var options = {
url: _getRequestBaseUrl() + 'Users',
method:'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
form: {
Identity: memberIdentity,
}
};
request(options, function(error, response, body) {
if (error) {
// User couldn't be created
}
// do stuff with user.
});
}
Could I also suggest you take a look at the Twilio helper library for Node.js. It handles the creation of URLs like you're doing for you. The code looks cleaner too, you can create a user with the helper library like this:
var accountSid = 'ACCOUNT_SID';
var authToken = 'AUTH_TOKEN';
var IpMessagingClient = require('twilio').IpMessagingClient;
var client = new IpMessagingClient(accountSid, authToken);
var service = client.services('SERVICE_SID');
service.users.create({
identity: 'IDENTITY'
}).then(function(response) {
console.log(response);
}).fail(function(error) {
console.log(error);
});
Let me know if this helps at all.
I am trying to modify the http status code of create.
POST /api/users
{
"lastname": "wqe",
"firstname": "qwe",
}
Returns 200 instead of 201
I can do something like that for errors:
var err = new Error();
err.statusCode = 406;
return callback(err, info);
But I can't find how to change status code for create.
I found the create method:
MySQL.prototype.create = function (model, data, callback) {
var fields = this.toFields(model, data);
var sql = 'INSERT INTO ' + this.tableEscaped(model);
if (fields) {
sql += ' SET ' + fields;
} else {
sql += ' VALUES ()';
}
this.query(sql, function (err, info) {
callback(err, info && info.insertId);
});
};
In your call to remoteMethod you can add a function to the response directly. This is accomplished with the rest.after option:
function responseStatus(status) {
return function(context, callback) {
var result = context.result;
if(testResult(result)) { // testResult is some method for checking that you have the correct return data
context.res.statusCode = status;
}
return callback();
}
}
MyModel.remoteMethod('create', {
description: 'Create a new object and persist it into the data source',
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
returns: {arg: 'data', type: mname, root: true},
http: {verb: 'post', path: '/'},
rest: {after: responseStatus(201) }
});
Note: It appears that strongloop will force a 204 "No Content" if the context.result value is falsey. To get around this I simply pass back an empty object {} with my desired status code.
You can specify a default success response code for a remote method in the http parameter.
MyModel.remoteMethod(
'create',
{
http: {path: '/', verb: 'post', status: 201},
...
}
);
For loopback verion 2 and 3+: you can also use afterRemote hook to modify the response:
module.exports = function(MyModel) {
MyModel.afterRemote('create', function(
context,
remoteMethodOutput,
next
) {
context.res.statusCode = 201;
next();
});
};
This way, you don't have to modify or touch original method or its signature. You can also customize the output along with the status code from this hook.
I use Filepicker to "read" then "store" an image from clients' computer. Now I want to resize the image using Filepicker but always get a 403 error:
POST https://www.filepicker.io/api/file/w11b6aScR1WRXKFbcXON/convert?_cacheBust=1380818787693 403 (FORBIDDEN)
I am using the same security policy and signature for the "read", "store", and "convert" calls. Is this wrong? Because when "read" and "store" are called there is no file handle yet (e.g. the last string part in InkBlob.url). But it seems the "convert" policy/signature must be generated using the file handle returned with the "store" InkBlob? And if this is the case, what's a more convenient way to do in javascript? Because in "convert" I have no access to the Python function that generates security policies unless I write an API call for that.
My code snippet as below (initialFpSecurityObj was pre-generated in Python using an empty handle):
filepicker.store(thumbFile, {
policy: initialFpSecurityObj.policy,
signature: initialFpSecurityObj.signature,
location: "S3",
path: 'thumbs/' + initialFpSecurityObj.uniqueName + '/',
},function(InkBlob){
console.log("Store successful:", JSON.stringify(InkBlob));
processThumb(InkBlob);
}, function(FPError){
console.error(FPError.toString());
});
var processThumb = function(InkBlob){
filepicker.convert(InkBlob, {
width: 800,
height: 600,
format: "jpg",
policy: initialFpSecurityObj.policy,
signature: initialFpSecurityObj.signature,
}, function(InkBlob){
console.log("thumbnail converted and stored at:", InkBlob);
}, function(FPError){
console.error(FPError);
};
}
Thanks a lot for the help.
--- EDIT ---
Below is the snippet for the Python code that generates initialFpSecurityObj
def generateFpSecurityOptions(handle, userId, policyLife=DEFAULT_POLICY_LIFE):
expiry = int(time() + policyLife)
json_policy = json.dumps({'handle': handle, 'expiry': expiry})
policy = base64.urlsafe_b64encode(json_policy)
secret = 'XXXXXXXXXXXXXX'
signature = hmac.new(secret, policy, hashlib.sha256).hexdigest()
uniqueName = hashlib.md5()
uniqueName.update(signature + repr(time()))
uniqueName = uniqueName.hexdigest() + str(userId)
return {'policy':policy, 'signature':signature, 'expiry':expiry, 'uniqueName':uniqueName}
fp_security_options = generateFpSecurityOptions(None, request.user.id)
Then in the django template fp_security_options is retrieved:
var initialFpSecurityObj = {{fp_security_options|as_json|safe}};
The way that generates fp_security_options is suspicious to me (former colleague's code) because the handle is None.
My recommendation would be to create two policies: one that is handle-bound and allows storing of the file, and another that is not handle-bound for the convert. In this case, you can set a shorter expiry time to increase the level of security, given that you are not specifying a handle.
Your problem is probably that your policy does not contain any "call" specifications. I suggest:
json_policy = json.dumps({'handle': handle, 'expiry': expiry, 'call':['pick','store','read','convert']})
but as our (very busy ;) brettcvz suggests, for conversion only, this is already enough:
json_policy = json.dumps({'handle': handle, 'expiry': expiry, 'call':'convert'})
You can find this in the security docs https://developers.inkfilepicker.com/docs/security/
If you still have issues, use a REST call, it's free. The following method is JavaScript and returns an url to the REST endpoint of filepicker which can be used to retrieve the converted image. The _options object looks like this
var myOptions = {
w: 150,
h: 150,
fit: "crop",
align: "faces",
format: "jpg",
quality: 86
};
and will work with all parameters specified of file pickers REST-API (check out https://developers.inkfilepicker.com/docs/web/#inkblob-images).
function getConvertedURL(_handle, _options, _policy, _signature) {
// basic url piece
var url = "https://www.filepicker.io/api/file/" + _handle + "/convert?";
// appending options
for (var option in _options) {
if (_options.hasOwnProperty(option)) {
url += option + "=" + _options[option] + "&";
}
}
// appending signed policy
url += "signature=" + _signature + "&policy=" + _policy;
return url;
}
So I finally figured it out myself, although I saw brettcvz's suggestion afterwards. The key is for 'convert' to work, I have to specify the exact handle of the uploaded file (i.e. the last bit of the string in InkBlob's url property returned from the 'store' or 'pickAndStore' call.
First thing I did was to edit the Python function generating the security policy and signature:
def generateFpSecurityOptions(handle, userId, policyLife=DEFAULT_POLICY_LIFE):
expiry = int(time() + policyLife)
json_policy = json.dumps({'handle': handle, 'expiry': expiry})
policy = base64.urlsafe_b64encode(json_policy)
secret = 'XXXXXXXXXXXXXX'
signature = hmac.new(secret, policy, hashlib.sha256).hexdigest()
if not handle == None:
uniqueName = handle
else:
uniqueName = hashlib.md5()
uniqueName.update(signature + repr(time()))
uniqueName = uniqueName.hexdigest() + str(userId)
return {'policy':policy, 'signature':signature, 'expiry':expiry, 'uniqueName':uniqueName}
fp_security_options = generateFpSecurityOptions(None, request.user.id)
Then I have to established the API call in our Django framework to get this security policy object dynamically via AJAX. I am fortunate that my colleague has previously written it. So I just call the API function in Javascript to retrieve the file-specific security policy object:
var initialFpSecurityObj = {{fp_security_options|as_json|safe}};
filepicker.store(thumbFile, {
policy: initialFpSecurityObj.policy,
signature: initialFpSecurityObj.signature,
access: "public"
}, function(InkBlob) {
processThumb(InkBlob);
}, function(FPError) {
console.error(FPError.toString());
}, function(progress) {
console.log("Loading: " + progress + "%");
});
var processThumb = function(InkBlob) {
var fpHandle = InkBlob.url.split('/').pop();
$.ajax({
url: API_BASE + 'file_picker_policy',
type: 'GET',
data: {
'filename': fpHandle
},
dataType: 'json',
success: function(data) {
var newFpSecurityObj = data.data;
filepicker.convert(InkBlob, {
width: 800,
height: 600,
format: "jpg",
policy: newFpSecurityObj.policy,
signature: newFpSecurityObj.signature,
}, {
location: "S3",
path: THUMB_FOLDER + '/' + newFpSecurityObj.uniqueName + '/',
}, function(fp) { // onSuccess
console.log("successfully converted and stored!");
// do what you want with the converted file
}, function(FPError) { // onError
console.error(FPError);
});
},
failure: function() {
alert("There was an error converting the thumbnail! Please try again.");
}
});
};