Added InvitationManager
Change-Id: I0928eabfd138167301a0f2976cf427f8a9e047e9
diff --git a/src/group-manager.js b/src/group-manager.js
new file mode 100644
index 0000000..4b43e01
--- /dev/null
+++ b/src/group-manager.js
@@ -0,0 +1,49 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var vanadium = require('vanadium');
+
+var defineClass = require('./util/define-class');
+
+var GroupManager = defineClass({
+ publics: {
+ createSyncGroup: function(name, prefixes) {
+ var self = this;
+
+ return this.prereq.then(function() {
+ var sg = self.syncbaseWrapper.syncGroup(self.sgAdmin, name);
+
+ var spec = sg.buildSpec(
+ prefixes,
+ [self.name('sgmt', name)]
+ );
+
+ /* TODO(rosswang): Right now, duplicate SyncBase creates on
+ * different SyncBase instances results in siloed SyncGroups.
+ * Revisit this logic once it merges properly. */
+ return sg.joinOrCreate(spec);
+ });
+ }
+ },
+
+ init: function(vanadiumWrapper, syncbaseWrapper, mountNames) {
+ this.syncbaseWrapper = syncbaseWrapper;
+
+ this.name = function() {
+ var parts = [mountNames.app];
+ Array.prototype.push.apply(parts, arguments);
+ return vanadium.naming.join(parts);
+ };
+
+ this.sgAdmin = this.name('sgadmin');
+
+ /* TODO(rosswang): Once Vanadium supports global sync-group admin
+ * creation, remove this. For now, use the first local SyncBase
+ * instance to administrate. */
+ this.prereq = vanadiumWrapper.mount(this.sgAdmin, syncbaseWrapper.mountName,
+ vanadiumWrapper.multiMount.FAIL);
+ }
+});
+
+module.exports = GroupManager;
\ No newline at end of file
diff --git a/src/invitation-manager.js b/src/invitation-manager.js
new file mode 100644
index 0000000..83488a9
--- /dev/null
+++ b/src/invitation-manager.js
@@ -0,0 +1,52 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var defineClass = require('./util/define-class');
+
+var InvitationManager = defineClass({
+ publics: {
+ invite: function(username) {
+ }
+ },
+
+ privates: {
+ /**
+ * TODO(rosswang): this is a very short term hack just because user mount
+ * names on ns.dev.v.io don't yet default to Resolve in [...].
+ */
+ advertise: function() {
+ return this.prereqs.then(function(prereqs) {
+ var mountNames = prereqs.mountNames;
+ var vanadiumWrapper = prereqs.vanadiumWrapper;
+ return vanadiumWrapper.getPermissions(mountNames.user)
+ .then(function(results) {
+ var perms = results[0];
+ perms.set('Resolve', {in: ['...']});
+ return vanadiumWrapper.setPermissions(mountNames.user, perms);
+ });
+ });
+ }
+ },
+
+ events: {
+ onError: 'memory'
+ },
+
+ /**
+ * @param prereqs promise of { mountNames, vanadiumWrapper }
+ */
+ init: function(prereqs, groupManagerPromise) {
+ this.prereqs = prereqs;
+
+ this.groupManagerPromise = groupManagerPromise;
+
+ this.createInvitationsSg = groupManagerPromise.then(function(gm) {
+ return gm.createSyncGroup('invitations', ['invitations']);
+ });
+
+ this.advertise().catch(this.onError);
+ }
+});
+
+module.exports = InvitationManager;
\ No newline at end of file
diff --git a/src/strings.js b/src/strings.js
index 1a94323..d5d0362 100644
--- a/src/strings.js
+++ b/src/strings.js
@@ -29,6 +29,7 @@
label: function(label, details) {
return label + ': ' + details;
},
+ 'Not connected': 'Not connected',
'Origin': 'Origin',
'Search': 'Search',
'Timeline': 'Timeline',
diff --git a/src/travel.js b/src/travel.js
index 78906ae..c3ff2df 100644
--- a/src/travel.js
+++ b/src/travel.js
@@ -72,12 +72,14 @@
}
function makeMountNames(id) {
- // TODO: first-class app-wide rather than siloed by account
- var parts = ['/ns.dev.v.io:8101', 'users', id.username, 'travel'];
+ var parts = ['/ns.dev.v.io:8101', 'users', id.username];
var names = {
user: vanadium.naming.join(parts)
};
+ parts.push('travel');
+ names.app = vanadium.naming.join(parts);
+
parts.push(id.deviceName);
names.device = vanadium.naming.join(parts);
@@ -353,11 +355,11 @@
wrapper.onCrash.add(error);
var identity = new Identity(wrapper.getAccountName());
- identity.mountNames = makeMountNames(identity);
+ var mountNames = makeMountNames(identity);
messages.setUsername(identity.username);
return {
- identity: identity,
+ mountNames: mountNames,
vanadiumWrapper: wrapper
};
});
@@ -476,7 +478,7 @@
this.commands = {
invite: {
op: function(username) {
- sync.invite(username);
+ this.sync.invitationManager.invite(username);
}
}
};
diff --git a/src/travelsync.js b/src/travelsync.js
index 9591da0..36f73e1 100644
--- a/src/travelsync.js
+++ b/src/travelsync.js
@@ -13,6 +13,8 @@
var defineClass = require('./util/define-class');
var debug = require('./debug');
+var GroupManager = require('./group-manager');
+var InvitationManager = require('./invitation-manager');
var Place = require('./place');
var vdlTravel = require('../ifc');
@@ -39,10 +41,6 @@
}
},
- invite: function(username) {
-
- },
-
message: function(messageContent) {
var id = uuid.v4();
var payload = $.extend({
@@ -390,7 +388,7 @@
var self = this;
var vanadiumWrapper = args.vanadiumWrapper;
- var identity = args.identity;
+ var mountNames = args.mountNames;
var sbName = queryString.parse(location.search).syncbase || 4000;
if ($.isNumeric(sbName)) {
@@ -402,46 +400,34 @@
.then(function(syncbase) {
syncbase.onError.add(self.onError);
syncbase.onUpdate.add(self.processUpdates);
-
- /* TODO(rosswang): Once Vanadium supports global sync-group admin
- * creation, remove this. For now, use the first local SyncBase
- * instance to administrate. */
- var sgAdmin = vanadium.naming.join(
- identity.mountNames.user, 'sgadmin');
- return vanadiumWrapper.mount(sgAdmin, sbName,
- vanadiumWrapper.multiMount.FAIL)
- .then(function() {
- var sg = syncbase.syncGroup(sgAdmin, 'trip');
-
- var spec = sg.buildSpec(
- [''],
- [vanadium.naming.join(identity.mountNames.user, 'sgmt')]
- );
-
- /* TODO(rosswang): Right now, duplicate SyncBase creates on
- * different SyncBase instances results in siloed SyncGroups.
- * Revisit this logic once it merges properly. */
- return sg.joinOrCreate(spec);
- })
- .then(function() {
- return syncbase;
- });
+ return syncbase;
});
+ var gmp = startSyncbase.then(function(syncbase) {
+ return new GroupManager(vanadiumWrapper, syncbase, mountNames);
+ });
+
+ var createPrimarySyncGroup = gmp.then(function(gm) {
+ return gm.createSyncGroup('trip', ['']);
+ });
+
return Promise.all([
vanadiumWrapper.server(
- vanadium.naming.join(identity.mountNames.device, 'rpc'), this.server),
- startSyncbase
+ vanadium.naming.join(mountNames.device, 'rpc'), this.server),
+ startSyncbase,
+ gmp,
+ createPrimarySyncGroup
]).then(function(values) {
return {
server: values[0],
- syncbase: values[1]
+ syncbase: values[1],
+ groupManager: values[2]
};
});
}
},
- constants: [ 'startup' ],
+ constants: [ 'startup', 'invitationManager' ],
events: {
/**
* @param newSize
@@ -465,12 +451,12 @@
},
/**
- * @param promise a promise that produces { mountName, vanadiumWrapper }.
+ * @param prereqs a promise that produces { mountNames, vanadiumWrapper }.
* @mapsDependencies an object with the following keys:
* maps
* placesService
*/
- init: function(promise, mapsDependencies) {
+ init: function(prereqs, mapsDependencies) {
var self = this;
this.mapsDeps = mapsDependencies;
@@ -480,7 +466,15 @@
this.destRecords = [];
this.server = new vdlTravel.TravelSync();
- this.startup = promise.then(this.start);
+ this.startup = prereqs.then(this.start);
+
+ this.invitationManager = new InvitationManager(
+ prereqs,
+ this.startup.then(function(services) {
+ return services.groupManager;
+ }));
+
+ this.invitationManager.onError.add(this.onError);
this.handleDestinationPlaceChange = function() {
self.updateDestinationPlace(this);
diff --git a/src/vanadium-wrapper/index.js b/src/vanadium-wrapper/index.js
index ba2a3a0..e136879 100644
--- a/src/vanadium-wrapper/index.js
+++ b/src/vanadium-wrapper/index.js
@@ -77,6 +77,16 @@
return refreshName();
},
+ getPermissions: function(name) {
+ return this.runtime.namespace().getPermissions(
+ this.runtime.getContext(), name);
+ },
+
+ setPermissions: function(name, perms) {
+ return this.runtime.namespace().setPermissions(
+ this.runtime.getContext(), name, perms);
+ },
+
/**
* @param endpoint Vanadium name
* @returns a promise resolving to a client or rejecting with an error.
diff --git a/src/vanadium-wrapper/syncbase-wrapper.js b/src/vanadium-wrapper/syncbase-wrapper.js
index dcb1080..d4f510e 100644
--- a/src/vanadium-wrapper/syncbase-wrapper.js
+++ b/src/vanadium-wrapper/syncbase-wrapper.js
@@ -84,7 +84,7 @@
var db = app.noSqlDatabase('db');
return setUp(context, app, db).then(function() {
- return new SyncbaseWrapper(context, db);
+ return new SyncbaseWrapper(context, db, mountName);
});
}
},
@@ -340,16 +340,21 @@
}
},
+ constants: [ 'mountName' ],
+
events: {
onError: 'memory',
onUpdate: 'memory'
},
- init: function(context, db) {
+ init: function(context, db, mountName) {
+ // TODO(rosswang): mountName probably won't be necessary after mount tables
+ // can spin up SyncBase instances (see group-manager).
var self = this;
this.context = context;
this.db = db;
this.t = db.table('t');
+ this.mountName = mountName;
this.writes = new Set();