diff --git a/lib/models.py b/lib/models.py index 7372486..b305a56 100644 --- a/lib/models.py +++ b/lib/models.py @@ -91,6 +91,10 @@ class Client(db.Model): class Subject(db.Model): name = db.StringProperty(required=True) + readable_only_by = db.ReferenceProperty( + reference_class=Profile, collection_name='readable_subject_set') + writable_only_by = db.ReferenceProperty( + reference_class=Profile, collection_name='writable_subject_set') @classmethod def FindOrCreate(cls, name): @@ -206,7 +210,9 @@ class Message(db.Model): 'event_type': 'message', 'id': self.key().id(), 'sender': str(Message.sender.get_value_for_datastore(self)), - 'subject': self.parent().name, + 'subject': { + 'name': self.parent().name, + }, 'created': self.created, 'message': self.message, } diff --git a/static/cosmopolite.js b/static/cosmopolite.js index b8e8039..b9a722e 100644 --- a/static/cosmopolite.js +++ b/static/cosmopolite.js @@ -110,10 +110,15 @@ Cosmopolite.prototype.subscribe = function(subject, messages, keys) { 'keys': keys, }; this.sendRPC_('subscribe', args, function() { - this.subscriptions_[subject] = { - 'messages': [], - 'keys': {}, - }; + if (subject in this.subscriptions_) { + console.log( + this.loggingPrefix_(), 'duplicate subject subscriptions:', subject); + } else { + this.subscriptions_[subject] = { + 'messages': [], + 'keys': {}, + }; + } resolve(); }.bind(this)); }.bind(this)); @@ -516,7 +521,7 @@ Cosmopolite.prototype.onServerEvent_ = function(e) { } break; case 'message': - var subscription = this.subscriptions_[e['subject']]; + var subscription = this.subscriptions_[e['subject']['name']]; if (!subscription) { console.log( this.loggingPrefix_(), diff --git a/static/test.js b/static/test.js index 84e1903..c225423 100644 --- a/static/test.js +++ b/static/test.js @@ -94,7 +94,7 @@ asyncTest('Message round trip', function() { var callbacks = { 'onMessage': function(e) { - equal(e['subject'], subject, 'subject matches'); + equal(e['subject']['name'], subject, 'subject matches'); equal(e['message'], message, 'message matches'); cosmo.shutdown(); start(); @@ -119,7 +119,7 @@ asyncTest('Overwrite key', function() { var callbacks = { 'onMessage': function(e) { messages++; - equal(e['subject'], subject, 'subject matches'); + equal(e['subject']['name'], subject, 'subject matches'); equal(e['key'], key, 'key matches'); if (messages == 1) { equal(e['message'], message1, 'message #1 matches'); @@ -156,7 +156,7 @@ asyncTest('Complex object', function() { var callbacks = { 'onMessage': function(e) { - equal(e['subject'], subject, 'subject matches'); + equal(e['subject']['name'], subject, 'subject matches'); deepEqual(e['message'], message, 'message matches'); cosmo.shutdown(); start(); @@ -209,7 +209,7 @@ asyncTest('Duplicate message suppression', function() { var callbacks = { 'onMessage': function (msg) { - equal(msg['subject'], subject, 'subject matches'); + equal(msg['subject']['name'], subject, 'subject matches'); equal(msg['key'], key, 'key matches'); equal(msg['message'], message1, 'message matches'); cosmo.shutdown(); @@ -245,7 +245,7 @@ asyncTest('Message persistence', function() { var callbacks = { 'onMessage': function(msg) { - equal(msg['subject'], subject, 'subject matches'); + equal(msg['subject']['name'], subject, 'subject matches'); equal(msg['message'], message, 'message matches'); cosmo2.shutdown(); start(); @@ -297,9 +297,12 @@ asyncTest('Profile merge', function() { var callbacks = { 'onMessage': function(msg) { messages++; - equal(msg['subject'], subject, 'message #' + messages + ': subject matches'); - equal(msg['message'], message, 'message #' + messages + ': message matches'); - equal(msg['sender'], cosmo.profile(), 'message #' + messages + ': profile matches'); + equal(msg['subject']['name'], subject, + 'message #' + messages + ': subject matches'); + equal(msg['message'], message, + 'message #' + messages + ': message matches'); + equal(msg['sender'], cosmo.profile(), + 'message #' + messages + ': profile matches'); if (messages == 1) { cosmo.unsubscribe(subject); // Entirely magic URL that sets the login cookie and redirects.