Skip to content

Instantly share code, notes, and snippets.

@rajagp
Last active May 30, 2022 23:19
Show Gist options
  • Save rajagp/42327d8ac06fcd6d2d47dffef162631c to your computer and use it in GitHub Desktop.
Save rajagp/42327d8ac06fcd6d2d47dffef162631c to your computer and use it in GitHub Desktop.
function sync(doc, oldDoc) {
// Every document write is processed by access control function
/* Data Validation */
// Validate the presence of email field.
validateNotEmpty("email", doc.email);
// Validate that the document Id _id is prefixed by owner
var expectedDocId = "user" + "::" + doc.email;
if (expectedDocId != doc._id) {
// reject documents that fail data validation
throw({forbidden: "user doc Id must be of form user::email"});
}
try {
// Check if this is document imported from server.
// All server side imports are processed using admin credentials
requireAdmin();
if (!isDelete()) {
// Derive channel name from content of document. Every user has own channel
var username = getEmail();
var channelId = "channel."+ username;
// Assign document to channel
channel(channelId);
// Give user access to channel
access(username,channelId);
}
}catch (error) {
// This is not a document import. It is a write coming in from client.
console.log("This is not a doc import " + error);
// If non admin client replication
if (!isDelete()) {
/* Authorization */
// Verify the user making the request is the same as the one in doc's email
requireUser(doc.email);
// Check if document is being created / added for first time
// We allow any user to create the document
if (isCreate()) {
/* Routing */
// Derive channel name using content of document. Every user has own channel.
var username = getEmail();
var channelId = "channel."+ username;
// Add doc to the channel.
channel(channelId);
// Give user access to document
access(username, channelId);
} else {
// This is an update
// Validate that the email hasn't changed.
validateReadOnly("email", doc.email, oldDoc.email);
var username = getEmail();
var channelId = "channel."+ username;
// Add doc to the user's channel.
channel(channelId);
// Give user access to channel
access(username,channelId);
}
}
}
// Helper functions
// get type property
function getType() {
return (isDelete() ? oldDoc.type : doc.type);
}
// get email Id property
function getEmail() {
return (isDelete() ? oldDoc.email : doc.email);
}
// Check if document is being created/added for first time
function isCreate() {
// Checking false for the Admin UI to work
return ((oldDoc == false) || (oldDoc == null || oldDoc._deleted) && !isDelete());
}
// Check if this is a document update
function isUpdate() {
return (!isCreate() && !isDelete());
}
// Check if this is a document delete
function isDelete() {
return (doc._deleted == true);
}
// Verify that specified property exists
function validateNotEmpty(key, value) {
if (!value) {
throw({forbidden: key + " is not provided."});
}
}
// Verify that specified property value has not changed during update
function validateReadOnly(name, value, oldValue) {
if (value != oldValue) {
throw({forbidden: name + " is read-only."});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment