From 5e7f6bead6e331de122696ec9a9fe15ffa2b1a39 Mon Sep 17 00:00:00 2001 From: Paul Mietz Egli Date: Wed, 18 Jun 2014 08:54:06 -0700 Subject: [PATCH 1/6] bumped version to 1.0.1 --- mobile/android/manifest | 2 +- mobile/ios/manifest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/android/manifest b/mobile/android/manifest index 93aed04..bd362ef 100644 --- a/mobile/android/manifest +++ b/mobile/android/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 1.0 +version: 1.0.1 apiversion: 2 description: TouchDB for Titanium author: Paul Mietz Egli diff --git a/mobile/ios/manifest b/mobile/ios/manifest index 0a3587d..1e9c413 100644 --- a/mobile/ios/manifest +++ b/mobile/ios/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 1.0 +version: 1.0.1 apiversion: 2 description: Titanium wrapper for Couchbase Mobile author: Paul Mietz Egli From e2d8ea97612689c77414f2c0dd8ef14539157473 Mon Sep 17 00:00:00 2001 From: Paul Mietz Egli Date: Wed, 18 Jun 2014 08:54:36 -0700 Subject: [PATCH 2/6] implemented ReplicationProxy setHeaders(), getHeaders(), and setCredential() --- .../obscure/titouchdb/ReplicationProxy.java | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java b/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java index 1a57679..4a910b6 100644 --- a/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java +++ b/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java @@ -8,6 +8,8 @@ import org.appcelerator.kroll.KrollProxy; import org.appcelerator.kroll.annotations.Kroll; +import com.couchbase.lite.auth.Authenticator; +import com.couchbase.lite.auth.AuthenticatorFactory; import com.couchbase.lite.replicator.Replication; import com.couchbase.lite.replicator.Replication.ChangeEvent; import com.couchbase.lite.replicator.Replication.ChangeListener; @@ -15,13 +17,13 @@ @Kroll.proxy(parentModule = TitouchdbModule.class) public class ReplicationProxy extends KrollProxy implements ChangeListener { - private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String[] EMPTY_STRING_ARRAY = new String[0]; - private static final String LCAT = "ReplicationProxy"; + private static final String LCAT = "ReplicationProxy"; private DatabaseProxy databaseProxy; - private KrollDict lastError = null; + private KrollDict lastError = null; private Replication replicator; @@ -30,7 +32,7 @@ public ReplicationProxy(DatabaseProxy databaseProxy, Replication replicator) { assert replicator != null; this.databaseProxy = databaseProxy; this.replicator = replicator; - + replicator.addChangeListener(this); } @@ -67,8 +69,7 @@ public KrollDict getFilterParams() { @Kroll.getProperty(name = "headers") public KrollDict getHeaders() { - // TODO - return null; + return TypePreprocessor.toKrollDict(replicator.getHeaders()); } @Kroll.getProperty(name = "localDatabase") @@ -107,7 +108,7 @@ public boolean isRunning() { return replicator.isRunning(); } - @Kroll.method(runOnUiThread=true) + @Kroll.method(runOnUiThread = true) public void restart() { replicator.restart(); } @@ -124,7 +125,13 @@ public void setCreateTarget(boolean createTarget) { @Kroll.method public void setCredential(KrollDict credential) { - // TODO + if (credential == null) { + replicator.setAuthenticator(null); + } + else { + Authenticator authenticator = AuthenticatorFactory.createBasicAuthenticator(credential.getString("user"), credential.getString("pass")); + replicator.setAuthenticator(authenticator); + } } @Kroll.setProperty(name = "docIds") @@ -138,21 +145,21 @@ public void setFilter(String filter) { } @Kroll.setProperty(name = "filterParams") - public void setFilterParams(String filterParams) { - // TODO + public void setFilterParams(KrollDict filterParams) { + replicator.setFilterParams(filterParams); } @Kroll.setProperty(name = "headers") - public void setHeaders(String headers) { - // TODO + public void setHeaders(KrollDict headers) { + replicator.setHeaders(headers); } - @Kroll.method(runOnUiThread=true) + @Kroll.method(runOnUiThread = true) public void start() { replicator.start(); } - @Kroll.method(runOnUiThread= true) + @Kroll.method(runOnUiThread = true) public void stop() { replicator.stop(); } @@ -162,7 +169,7 @@ public void changed(ChangeEvent e) { KrollDict params = new KrollDict(); params.put("source", this); params.put("status", replicator.getStatus().ordinal()); - + fireEvent("status", params); } From 5f1330aba6187e1af6f10645aa5131e42e192380 Mon Sep 17 00:00:00 2001 From: Paul Mietz Egli Date: Tue, 17 Jun 2014 15:19:54 -0700 Subject: [PATCH 3/6] fixed problem with alloy adapter when fetching individual documents --- mobile/noarch/alloy/sync/titouchdb.js | 86 ++++++++++++++++++--------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/mobile/noarch/alloy/sync/titouchdb.js b/mobile/noarch/alloy/sync/titouchdb.js index e1fb630..c4fa773 100755 --- a/mobile/noarch/alloy/sync/titouchdb.js +++ b/mobile/noarch/alloy/sync/titouchdb.js @@ -5,8 +5,7 @@ var _ = require('alloy/underscore'), titouchdb = require('com.obscure.titouchdb'), manager = titouchdb.databaseManager, - db, - modelname; + db; /** @@ -78,64 +77,84 @@ function InitAdapter(config) { function Sync(method, model, options) { var opts = options || {}; + var resp = null, err = null; switch (method) { case 'create': var props = model.toJSON(); - props.modelname = model.config.adapter.modelname; + _.extend(props, model.config.adapter.static_properties || {}); var doc = model.id ? db.getDocument(model.id) : db.createDocument(); doc.putProperties(props); - model.id = doc.documentID; - model.trigger('create'); + err = doc.error; + if (!err) { + model.set(doc.properties, { silent: true }); + model.id = doc.documentID; + resp = model.toJSON(); + !opts.silent && model.trigger('change', { fromAdapter: true }); + } + break; case 'read': - if (opts.parse) { + if (model.idAttribute) { + // fetch a single model + var obj = opts.id ? db.getDocument(opts.id) : db.createDocument(); + if (obj) { + model.set(obj.properties); + model.id = obj.documentID; + !opts.silent && model.trigger('fetch', { fromAdapter: true }); + resp = model.toJSON(); + } + err = db.error; + } + else { var collection = model; // just to clear things up // collection var view = opts.view || collection.config.adapter.views[0]["name"]; - + collection.view = view; + // add default view options from model opts = _.defaults(opts, collection.config.adapter.view_options); var query = query_view(db, view, opts); if (!query) { + err = { error: 'missing view' }; break; } var rows = query.run(); - - // do not use Collection methods! - var len = 0; - if (!opts.add) { - collection.models = []; + if (rows.error) { + err = rows.error; + break; } + + var len = 0, values = []; while (row = rows.next()) { var m = collection.map_row(collection.model, row); if (m) { - collection.models.push(m); + values.push(m); ++len; } } - collection.view = view; - collection.length = len; - collection.trigger('fetch'); - } - else { - // object - var obj = db.getDocument(model.id) - model.set(obj.properties); - model.id = obj.documentID; - model.trigger('fetch'); + + resp = 1 === len ? values[0] : values; + !opts.silent && collection.trigger('fetch', { fromAdapter: true }); } break; case 'update': var props = model.toJSON(); - props.modelname = model.config.adapter.modelname; + _.extend(props, model.config.adapter.static_properties || {}); var doc = db.getDocument(model.id); - doc.putProperties(model.toJSON()); - model.trigger('update'); + doc.putProperties(props); + err = doc.error; + if (!err) { + model.set(doc.properties, { silent: true }); + model.id = doc.documentID; + resp = model.toJSON(); + !opts.silent && model.trigger('change', { fromAdapter: true }); + } + break; case 'delete': @@ -143,10 +162,20 @@ function Sync(method, model, options) { var doc = db.getDocument(model.id); doc.deleteDocument(); model.id = null; - model.trigger('destroy'); + err = doc.error; + if (!err) { + resp = model.toJSON(); + !opts.silent && model.trigger('destroy', { fromAdapter: true }); + } } break; - } + } + + if (resp) { + _.isFunction(opts.success) && opts.success(resp); + } else { + _.isFunction(opts.error) && opts.error(resp); + } } module.exports.sync = Sync; @@ -164,6 +193,7 @@ module.exports.afterModelCreate = function(Model) { Model.prototype.idAttribute = '_id'; // true for all TouchDB documents Model.prototype.config.Model = Model; // needed for fetch operations to initialize the collection from persistent store + Model.prototype.database = db; Model.prototype.attachmentNamed = function(name) { var doc = db.getDocument(this.id); From 1f19ff8f98404a601c2ca044d4d5aa3f5712bb9f Mon Sep 17 00:00:00 2001 From: Paul Mietz Egli Date: Thu, 19 Jun 2014 12:33:02 -0700 Subject: [PATCH 4/6] fixed crashing problem in setCredential() --- .../src/com/obscure/titouchdb/ReplicationProxy.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java b/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java index 4a910b6..482d8c0 100644 --- a/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java +++ b/mobile/android/src/com/obscure/titouchdb/ReplicationProxy.java @@ -124,12 +124,15 @@ public void setCreateTarget(boolean createTarget) { } @Kroll.method - public void setCredential(KrollDict credential) { + public void setCredential(@Kroll.argument(optional=true) KrollDict credential) { if (credential == null) { replicator.setAuthenticator(null); } else { - Authenticator authenticator = AuthenticatorFactory.createBasicAuthenticator(credential.getString("user"), credential.getString("pass")); + // oddly enough, KrollDict.getString() crashes... + String user = (String) credential.get("user"); + String pass = (String) credential.get("pass"); + Authenticator authenticator = AuthenticatorFactory.createBasicAuthenticator(user, pass); replicator.setAuthenticator(authenticator); } } From 38f8f9768143120fafaef6c41769d10c6869c06b Mon Sep 17 00:00:00 2001 From: Paul Mietz Egli Date: Thu, 19 Jun 2014 12:35:19 -0700 Subject: [PATCH 5/6] added sync logging to LiteServ run command --- mobile/noarch/example/LiteServ/run_liteserv.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/noarch/example/LiteServ/run_liteserv.sh b/mobile/noarch/example/LiteServ/run_liteserv.sh index 17c8b28..5193aaa 100755 --- a/mobile/noarch/example/LiteServ/run_liteserv.sh +++ b/mobile/noarch/example/LiteServ/run_liteserv.sh @@ -1,5 +1,5 @@ #!/bin/bash DATA=$(mktemp -d /tmp/liteserv.XXXXX) cp -R ../assets/CouchbaseLite/elements* ${DATA} -./bin/LiteServ --dir ${DATA} -LogSync -LogSyncVerbose -rm -Rf ${DATA} \ No newline at end of file +./bin/LiteServ --dir ${DATA} -Log YES -LogSync YES -LogSyncVerbose YES +rm -Rf ${DATA} From cacceda9cb4f6f6429d27b6f584622319f32f9e4 Mon Sep 17 00:00:00 2001 From: Paul Mietz Egli Date: Thu, 19 Jun 2014 12:35:39 -0700 Subject: [PATCH 6/6] added unit test for setting replication credentials --- mobile/noarch/example/013_replication.js | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mobile/noarch/example/013_replication.js b/mobile/noarch/example/013_replication.js index efcd48c..bee46e9 100644 --- a/mobile/noarch/example/013_replication.js +++ b/mobile/noarch/example/013_replication.js @@ -165,4 +165,31 @@ module.exports = function() { repl.start(); }); }); + + describe('pull replication with auth credentials', function() { + var conf, repl; + + before(function(done) { + utils.delete_nonsystem_databases(manager); + conf = utils.verify_couchdb_server('replication_config.json', done); + }); + + // currently returning a 400 error due to a request for /elements/_session + it.skip('must replicate with credentials', function(done) { + this.timeout(10000); + var db = manager.getDatabase('repl3'); + repl = db.createPullReplication('http://'+conf.host+':'+conf.port+'/'+conf.dbname); + repl.setCredential({ user: 'scott', pass: 'tiger' }); + repl.addEventListener('status', function(e) { + if (e.status == titouchdb.REPLICATION_MODE_STOPPED) { + should.not.exist(repl.lastError); + db.documentCount.should.eql(118); + repl.isRunning.should.eql(false); + done(); + } + }); + repl.start(); + }); + }); + }; \ No newline at end of file