Commit ad6aae46 authored by Sven Franck's avatar Sven Franck

webDav Storage: putAttachment new API and qunit tests

parent 326eba96
...@@ -88,22 +88,31 @@ jIO.addStorageType('dav', function (spec, my) { ...@@ -88,22 +88,31 @@ jIO.addStorageType('dav', function (spec, my) {
return $.support.cors; return $.support.cors;
}; };
// wedDav methods rfc4918 // wedDav methods rfc4918 (short summary)
// PROPFIND // COPY Reproduces single resources (files) and collections (directory
// PROPPATCH // trees). Will overwrite files (if specified by request) but will
// MCKOL // respond 209 (Conflict) if it would overwrite a tree
// GET // DELETE deletes files and directory trees
// > resource = return content of element xyz.abc // GET just the vanilla HTTP/1.1 behaviour
// > collection > allDocs // HEAD ditto
// > attachment = return content of element xyz_.abc/att.def // LOCK locks a resources
// HEAD // MKCOL creates a directory
// POST // MOVE Moves (rename or copy) a file or a directory tree. Will
// DELETE // 'overwrite' files (if specified by the request) but will respond
// PUT // 209 (Conflict) if it would overwrite a tree.
// COPY // OPTIONS If WebDAV is enabled and available for the path this reports the
// MOVE // WebDAV extension methods
// LOCK // PROPFIND Retrieves the requested file characteristics, DAV lock status
// UNLOCK // and 'dead' properties for individual files, a directory and its
// child files, or a directory tree
// PROPPATCHset and remove 'dead' meta-data properties
// PUT Update or create resource or collections
// UNLOCK unlocks a resource
// Notes: all Ajax requests should be CORS (cross-domain)
// adding custom headers triggers preflight OPTIONS request!
// http://remysharp.com/2011/04/21/getting-cors-working/
priv.putOrPost = function (command, type) { priv.putOrPost = function (command, type) {
var doc = command.getDocId(), var doc = command.getDocId(),
...@@ -241,17 +250,154 @@ jIO.addStorageType('dav', function (spec, my) { ...@@ -241,17 +250,154 @@ jIO.addStorageType('dav', function (spec, my) {
}); });
}; };
/**
* Creates a new document
* @method post
* @param {object} command The JIO command
*/
that.post = function (command) { that.post = function (command) {
priv.putOrPost(command, 'POST'); priv.putOrPost(command, 'POST');
}; };
/** /**
* Saves a document in the distant dav storage. * Creates or updates a document
* @method put * @method put
* @param {object} command The JIO command
*/ */
that.put = function (command) { that.put = function (command) {
priv.putOrPost(command, 'PUT'); priv.putOrPost(command, 'PUT');
}; // end put };
/**
* Add an attachment to a document
* @method putAttachment
* @param {object} command The JIO command
*/
that.putAttachment = function (command) {
var docid = command.getDocId(), doc,
secured_docid, secured_attachmentid, attachment_url;
// no docId
if (!(typeof docid === "string" && docid !== "")) {
that.error({
"status": 405,
"statusText": "Method Not Allowed",
"error": "method_not_allowed",
"message": "Cannot create document which id is undefined",
"reason": "Document id is undefined"
});
return;
}
// no cross domain ajax
if (priv.checkCors === false) {
that.error({
"status": 405,
"statusText": "Method Not Allowed",
"error": "method_not_allowed",
"message": "Browser does not support cross domain ajax requests",
"reason": "cors is undefined"
});
return;
}
secured_docid = priv.secureDocId(docid);
url = priv.url + '/' + secured_docid;
// see if the underlying document exists ||
$.ajax({
url: url + '?_=' + Date.now(),
type: 'GET',
async: true,
dataType: 'text',
crossdomain : true,
headers : {
Authorization: 'Basic ' + Base64.encode(
priv.username + ':' + priv.password
)
},
success: function (response) {
doc = JSON.parse(response);
// the document exists - update document
doc._attachments = doc._attachments || {};
doc._attachments[command.getAttachmentId()] = {
"content_type": command.getAttachmentMimeType(),
"digest": "md5-" + command.md5SumAttachmentData(),
"length": command.getAttachmentLength()
};
// put updated document data
$.ajax({
url: url + '?_=' + Date.now(),
type: 'PUT',
data: doc,
async: true,
crossdomain: true,
headers : {
Authorization: 'Basic ' + Base64.encode(
priv.username + ':' + priv.password
)
},
// xhrFields: {withCredentials: 'true'},
success: function () {
secured_attachmentid = priv.secureDocId(command.getAttachmentId());
attachment_url = url + '/' + secured_attachmentid;
$.ajax({
url: attachment_url + '?_=' + Date.now(),
type: 'PUT',
data: command.getDoc(),
async: true,
crossdomain: true,
headers : {
Authorization: 'Basic ' + Base64.encode(
priv.username + ':' + priv.password
)
},
// xhrFields: {withCredentials: 'true'},
success: function (response) {
that.success({
ok: true,
id: command.getDocId()+'/'+command.getAttachmentId()
});
},
error: function (type) {
that.error({
"status": 409,
"statusText": "Conflicts",
"error": "conflicts",
"message": "Cannot modify document",
"reason": "Error trying to save attachment to remote storage"
});
return;
}
});
},
error: function (type) {
that.error({
"status": 409,
"statusText": "Conflicts",
"error": "conflicts",
"message": "Cannot modify document",
"reason": "Error trying to write to remote storage"
});
return;
}
});
},
error: function () {
// the document does not exist
that.error({
"status": 404,
"statusText": "Not Found",
"error": "not_found",
"message": "Impossible to add attachment",
"reason": "Document not found"
});
return;
}
});
};
/** /**
* Loads a document from a distant dav storage. * Loads a document from a distant dav storage.
......
...@@ -239,6 +239,7 @@ generateTools = function (sinon) { ...@@ -239,6 +239,7 @@ generateTools = function (sinon) {
o.addFakeServerResponse = function (method, path, status, response) { o.addFakeServerResponse = function (method, path, status, response) {
var url = new RegExp('https:\\/\\/ca-davstorage:8080\\/' + path + var url = new RegExp('https:\\/\\/ca-davstorage:8080\\/' + path +
'(\\?.*|$)'); '(\\?.*|$)');
// console.log("adding response for: "+method+" "+url );
o.server.respondWith(method, url, o.server.respondWith(method, url,
[status, { "Content-Type": 'application/xml' }, response] [status, { "Content-Type": 'application/xml' }, response]
); );
...@@ -2049,14 +2050,15 @@ test ("Post", function () { ...@@ -2049,14 +2050,15 @@ test ("Post", function () {
o.addFakeServerResponse("GET", "myFile", 200, o.answer); o.addFakeServerResponse("GET", "myFile", 200, o.answer);
o.spy (o, "status", 409, "Post but document already exists"); o.spy (o, "status", 409, "Post but document already exists");
o.jio.post({"_id": "myFile", "title": "hello again"}, o.f); o.jio.post({"_id": "myFile", "title": "hello again"}, o.f);
o.clock.tick(1000);
o.server.respond();
o.clock.tick(5000); o.clock.tick(5000);
o.server.respond();
// as all custom headers trigger preflight requests, the test also
// need to simulate CORS (cross domain ajax with preflight)
// custom header may be authentication for example
o.jio.stop(); o.jio.stop();
// do the same tests live webDav-Server // do the same tests live webDav-Server simulating CORS!
// check for credentials in sinon
/* also check for equality /* also check for equality
deepEqual( deepEqual(
...@@ -2093,6 +2095,9 @@ test ("Put", function(){ ...@@ -2093,6 +2095,9 @@ test ("Put", function(){
o.jio.put({"_id": "put1", "title": "myPut1"}, o.f); o.jio.put({"_id": "put1", "title": "myPut1"}, o.f);
o.clock.tick(5000); o.clock.tick(5000);
o.server.respond(); o.server.respond();
//console.log( o.server );
//console.log( o.server.requests[0].requestHeaders );
//console.log( o.server.requests[0].responseHeaders );
// put but document already exists = update // put but document already exists = update
o.answer = JSON.stringify({"_id": "put1", "title": "myPut1"}); o.answer = JSON.stringify({"_id": "put1", "title": "myPut1"});
...@@ -2105,10 +2110,73 @@ test ("Put", function(){ ...@@ -2105,10 +2110,73 @@ test ("Put", function(){
o.jio.stop(); o.jio.stop();
// do the same tests live webDav-Server // do the same tests live webDav-Server/simulate CORS
// check for credentials in sinon // check for credentials in sinon
}); });
test ("PutAttachment", function(){
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "dav",
"username": "davput",
"password": "checkpwd",
"url": "https://ca-davstorage:8080"
});
// putAttachment without doc id => id required
o.spy(o, "status", 20, "PutAttachment without doc id");
o.jio.putAttachment({}, o.f);
o.clock.tick(5000);
// putAttachment without attachment id => attachment id required
o.spy(o, "status", 22, "PutAttachment without attachment id");
o.jio.putAttachment({"id": "putattmt1"}, o.f);
o.clock.tick(5000);
// putAttachment without underlying document => not found
o.addFakeServerResponse("GET", "putattmtx", 404, "HTML RESPONSE");
o.spy(o, "status", 404, "PutAttachment without document");
o.jio.putAttachment({"id": "putattmtx/putattmt2"}, o.f);
o.clock.tick(5000);
o.server.respond();
// putAttachment with document without data
o.answer = JSON.stringify({"_id": "putattmt1", "title": "myPutAttm1"});
o.addFakeServerResponse("GET", "putattmt1", 200, o.answer);
o.addFakeServerResponse("PUT", "putattmt1", 201, "HTML RESPONSE");
o.addFakeServerResponse("PUT", "putattmt1/putattmt2", 201,"HTML RESPONSE");
o.spy(o, "value", {"ok": true, "id": "putattmt1/putattmt2"},
"PutAttachment with document, without data");
o.jio.putAttachment({"id": "putattmt1/putattmt2"}, o.f);
o.clock.tick(5000);
o.server.respond();
// check document
// check attachment
// update attachment
o.answer = JSON.stringify({"_id": "putattmt1", "title": "myPutAttm1"});
o.addFakeServerResponse("GET", "putattmt1", 200, o.answer);
o.addFakeServerResponse("PUT", "putattmt1", 201, "HTML RESPONSE");
o.addFakeServerResponse("PUT", "putattmt1/putattmt2", 201,"HTML RESPONSE");
o.spy(o, "value", {"ok": true, "id": "putattmt1/putattmt2"},
"Update Attachment, with data");
o.jio.putAttachment({"id": "putattmt1/putattmt2", "data": "abc"}, o.f);
o.clock.tick(5000);
o.server.respond();
// check document
// check attachment
o.jio.stop();
// do the same tests live webDav-Server/simulate CORS
// check for credentials in sinon
});
/* /*
// note: http errno: // note: http errno:
// 200 OK // 200 OK
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment