Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Add have* functions to sync function scope #286

wants to merge 1 commit into from

3 participants


Add haveUser, haveRole and haveAccess functions that can be used in the sync function.

Example use case:

// only doc.members and admins can modify the document
if (!haveUser(oldDoc.members) && !haveRole('admin')) {
  throw ({forbidden: "no access"});

@jchris, what do you think of these? They seem like the existing requireUser, except that they can be combined into more complex tests.

@jessliu jessliu added the P3: major label

So, the reason for the restricted set of tests is that the sync function sometimes has to be re-run on a document later on. (For example, if you change a db's sync fn, the new fn has to be called on every doc in the db to update its channels.) But at that point there's no change being made to the document, nor a user making the change. And it doesn't really make sense to check access because the doc's already in the database. So what we do in that case is make all the require... functions succeed.

My worry is that if we had have... functions they could be used in ways that won't work properly when the sync fn is re-run. For example if you tried to use a role to block access:

if (haveRole('troll')) {
  throw ({forbidden: "your posting privileges have been revoked!"});

This would break during the re-scan of the db, because haveRole would always return true, so all documents would be rejected.


Yes, I actually ran in to that myself using these.

What about something like general require functions instead:

requireAll('user:id', 'role:admin') // throws if any fails
requireAny('channel:mychan', 'role:admin') // throws if all fails

// or perhaps with an object
requireAny({channels: [], users: ['name', 'names'], roles: ['admin']})
// where any of those can be omitted and you can pass an array or a string like the requireX functions
@jessliu jessliu added this to the Future milestone
@jessliu jessliu added the enhancement label
@snej snej added P4: minor enhancement and removed P3: major labels
@snej snej added the icebox label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 2, 2014
  1. @jnordberg
This page is out of date. Refresh to see the latest.
Showing with 24 additions and 12 deletions.
  1. +24 −12 src/
36 src/
@@ -47,25 +47,37 @@ const funcWrapper = `
// Proxy userCtx that allows queries but not direct access to user/roles:
var shouldValidate = (realUserCtx != null && != null);
+ function haveUser(names) {
+ if (!shouldValidate) return true;
+ names = makeArray(names);
+ return (inArray(, names));
+ }
+ function haveRole(roles) {
+ if (!shouldValidate) return true;
+ roles = makeArray(roles);
+ return (anyInArray(realUserCtx.roles, roles));
+ }
+ function haveAccess(channels) {
+ if (!shouldValidate) return true;
+ channels = makeArray(channels);
+ return (anyInArray(realUserCtx.channels, channels));
+ }
function requireUser(names) {
- if (!shouldValidate) return;
- names = makeArray(names);
- if (!inArray(, names))
- throw({forbidden: "wrong user"});
+ if (!haveUser(names))
+ throw({forbidden: "wrong user"});
function requireRole(roles) {
- if (!shouldValidate) return;
- roles = makeArray(roles);
- if (!anyInArray(realUserCtx.roles, roles))
- throw({forbidden: "missing role"});
+ if (!haveRole(roles))
+ throw({forbidden: "missing role"});
function requireAccess(channels) {
- if (!shouldValidate) return;
- channels = makeArray(channels);
- if (!anyInArray(realUserCtx.channels, channels))
- throw({forbidden: "missing channel access"});
+ if (!haveAccess(channels))
+ throw({forbidden: "missing channel access"});
try {
Something went wrong with that request. Please try again.