Skip to content

Instantly share code, notes, and snippets.

@npomfret
Created October 19, 2016 08:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save npomfret/93bb19bac152ff05a8831e08544e85b2 to your computer and use it in GitHub Desktop.
Save npomfret/93bb19bac152ff05a8831e08544e85b2 to your computer and use it in GitHub Desktop.
function (newDoc, oldDoc) {
if (oldDoc && oldDoc._deleted) {
throw({forbidden: "Attempt to edit a deleted doc"});
}
if (oldDoc) {
var previousOwners = [];
if (oldDoc.owners) {
for (var i in oldDoc.owners) {
previousOwners.push(oldDoc.owners[i]);
}
} else if (oldDoc.owner) {
previousOwners.push(oldDoc.owner)
}
if (previousOwners.length > 0) {
previousOwners.push('admin');
requireUser(previousOwners);
}
}
function assignToChannels(doc) {
if (doc.owner) {
channel('ch_private_' + doc.owner);
}
if (!doc.type) {
return;
}
if (doc.recipients) {
for (var rec in doc.recipients) {
channel('ch_private_' + doc.recipients[rec]);
}
}
if (doc.type === 'chat-message') {
if (doc.delivery_receipts_by_owner) {
for (var userId in doc.delivery_receipts_by_owner) {
channel('ch_private_' + userId);
}
}
if (doc.read_receipts_by_owner) {
for (var userId in doc.read_receipts_by_owner) {
channel('ch_private_' + userId);
}
}
// background images are 'public' so when you join a chat group you always see the background images - bit of a bodge
if(doc.content && doc.content.type === 'background-image') {
channel('ch_' + doc.chat_group_id);
}
} else if (doc.type === 'delivery-receipt' || doc.type === 'read-receipt') {
// doc.recipients... handled above
} else if (doc.type === 'live-chat') {
// doc.recipients... handled above
} else if (doc.type === 'chat-message-annotation') {
// doc.recipients... handled above
} else if (doc.type === 'request-message') {
// doc.owner... handled above
} else if (doc.type === 'time-delayed') {
// doc.owner... handled above
} else if (doc.type === 'gps-position') {
// doc.owner... handled above
} else if (doc.type === 'admin-request') {
// doc.owner... handled above
} else if (doc.type === 'chat-group-settings') {
// doc.owner... handled above
} else if (doc.type === 'address-book-entry') {
// doc.owner... handled above
} else if (doc.type === 'build-info') {
channel('ch_global_docs')
} else if (doc.type === 'public-image') {
channel('ch_global_docs')
} else if (doc.type === 'attachment') {
if (doc.readers) {
for (var r in doc.readers) {
channel('ch_private_' + doc.readers[r]);
}
}
} else if (doc.type === 'chat-group') {
var channelName = 'ch_' + doc._id;
channel(channelName);
if (doc.owners) {
access(doc.owners, channelName);
}
if (doc.members) {
access(doc.members, channelName);
}
if (doc.readers) {
access(doc.readers, channelName);
}
} else if (doc.type === 'account') {
channel('ch_private_' + doc.user_id);
} else if (doc.type === 'public-status') {
channel('ch_public_' + doc.owner);
} else if (doc.type === 'public-profile') {
channel('ch_public_' + doc.owner);
// make sure the user has access to all their abandoned chat groups
if(doc.abandoned_chat_groups) {
for(var abandonedChatGroupId in doc.abandoned_chat_groups) {
access(doc.owner, 'ch_' + abandonedChatGroupId);
}
}
}
}
if (newDoc._deleted) {
assignToChannels(oldDoc);
} else {
// cannot do validation checks on deleted docs
// http://developer.couchbase.com/documentation/mobile/1.2/develop/guides/sync-gateway/sync-function-api-guide/validation/index.html
if (newDoc.state && newDoc.state === 'archived') {
return;
}
if (!newDoc.type) {
throw({forbidden: "All docs must have a type"});
}
var requiredFields = function(doc, fieldNames) {
for(var i in fieldNames) {
var name = fieldNames[i];
if(!doc.hasOwnProperty(name)) {
throw {forbidden: "Doc '" + doc.type + "' must have field called '" + name + "'"}
}
if(doc[name] === null) {
throw {forbidden: "Doc '" + doc.type + "' must have not-null field called '" + name + "'"}
}
}
};
if (newDoc.type === 'chat-message') {
requiredFields(newDoc, ['owner', 'chat_group_id', 'client_timestamp_utc', 'content']);
if (!newDoc.content.type) {
throw {forbidden: "Doc '" + newDoc.type + "' must have a content.type"}
}
requireRole(['admin', "contrib_" + newDoc.chat_group_id]);
} else if (newDoc.type === 'attachment') {
requiredFields(newDoc, ['owner', 'chat_group_id', 'chat_message_id', 'client_timestamp_utc']);
requireRole(['admin', "contrib_" + newDoc.chat_group_id]);
} else if (newDoc.type === 'delivery-receipt' || newDoc.type === 'read-receipt') {
requiredFields(newDoc, ['owner', 'chat_group_id', 'recipients', 'chat_message_id', 'owner']);
} else if (newDoc.type === 'request-message') {
requiredFields(newDoc, ['owner', 'chat_group_id', 'client_timestamp_utc', 'content']);
if (!newDoc.content.type) {
throw {forbidden: "Doc '" + newDoc.type + "' must have a content.type"}
}
requireRole(['admin', "contrib_" + newDoc.chat_group_id]);
} else if (newDoc.type === 'live-chat') {
requiredFields(newDoc, ['owner', 'chat_group_id']);
requireRole(['admin', "contrib_" + newDoc.chat_group_id]);
} else if (newDoc.type === 'chat-group') {
//todo - name and access_code (both can be null)
requiredFields(newDoc, ['owners', 'readers', 'members', 'features']);
var chatGroupId = newDoc._id;
if (newDoc.owners) {
for (var o in newDoc.owners) {
role(newDoc.owners[o], "role:contrib_" + chatGroupId);
}
}
if (newDoc.members) {
for (var m in newDoc.members) {
role(newDoc.members[m], "role:contrib_" + chatGroupId);
}
}
} else if (newDoc.type === 'chat-message-annotation') {
requiredFields(newDoc, ['owner', 'chat_group_id', 'chat_message_id']);
requireRole(['admin', "contrib_" + newDoc.chat_group_id]);
} else if (newDoc.type === 'chat-group-settings') {
requiredFields(newDoc, ['owner', 'chat_group_id']);
} else if (newDoc.type === 'build-info') {
} else if (newDoc.type === 'address-book-entry') {
requiredFields(newDoc, ['owner', 'encrypted_contact']);
} else if (newDoc.type === 'public-image') {
} else if (newDoc.type === 'admin-request') {
} else if (newDoc.type === 'gps-position') {
requiredFields(newDoc, ['owner']);
} else if (newDoc.type === 'time-delayed') {
requiredFields(newDoc, ['owner', 'underlying', 'send_time']);
} else if (newDoc.type === 'public-status') {
requiredFields(newDoc, ['owner', 'client_timestamp_utc', 'viewName', 'active']);
} else if (newDoc.type === 'account') {
requiredFields(newDoc, ['owner', 'view_preferences', 'push_notification_token', 'trusters']);
} else if (newDoc.type === 'public-profile') {
requiredFields(newDoc, ['owner', 'account_id', 'trustees']);
} else {
throw({forbidden: "Invalid type: " + newDoc.type});
}
assignToChannels(newDoc);
if(oldDoc) {
assignToChannels(oldDoc);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment