Created
July 26, 2012 04:02
-
-
Save hannahwhy/3180173 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // this is set to validation/helpers | |
| (function (ex) { | |
| var knownTypes = [ | |
| 'event', | |
| 'profile', | |
| 'source_resolution', | |
| 'video' | |
| ]; | |
| ex.isKnownType = function (type) { | |
| return knownTypes.indexOf(type) !== -1; | |
| }; | |
| ex.userHasRole = function (userCtx) { | |
| return function (role) { | |
| return userCtx.roles.indexOf(role) !== -1; | |
| } | |
| }; | |
| ex.userIn = function (userCtx) { | |
| return function (list) { | |
| return list && list.indexOf(userCtx.name) !== -1; | |
| } | |
| }; | |
| ex.enforce = function (cond, message) { | |
| if (!cond) { | |
| throw({forbidden: message}); | |
| } | |
| }; | |
| ex.notBlank = function (str) { | |
| return str && str.trim() !== ''; | |
| }; | |
| ex.abort = function () { | |
| throw({forbidden: 'Permission denied.'}); | |
| }; | |
| return ex; | |
| })(exports); | |
| function (newDoc, oldDoc, userCtx, secObj) { | |
| var libs = require('validation/helpers'), | |
| isDeletion = newDoc['_deleted'], | |
| isKnownType = libs.isKnownType, | |
| enforce = libs.enforce, | |
| notBlank = libs.notBlank, | |
| userIn = libs.userIn(userCtx), | |
| userHasRole = libs.userHasRole(userCtx), | |
| isMember = userHasRole('member'), | |
| abort = libs.abort, | |
| ok; | |
| // If this is a deletion, carry out the deletion rules. | |
| if (isDeletion) { | |
| switch (oldDoc['type']) { | |
| case 'event': | |
| // Events can only be deleted by their organizers. | |
| ok = userIn(oldDoc['organizers']); | |
| enforce(ok, 'You cannot delete events you do not organize.'); | |
| break; | |
| case 'profile': | |
| // Profiles can only be deleted by their owners. | |
| ok = oldDoc['username'] === userCtx.name; | |
| enforce(ok, "You cannot delete another user's profile."); | |
| break; | |
| case 'source_resolution': | |
| // Only source resolvers can delete resolution documents. | |
| ok = userHasRole('source_resolver'); | |
| enforce(ok, 'You cannot delete resolution documents.'); | |
| break; | |
| case 'video': | |
| // Videos can only be deleted by their owners or video DB admins. | |
| ok = userIn(oldDoc['owners']) || userHasRole('video_db_admin'); | |
| enforce(ok, 'You cannot delete videos you do not own.'); | |
| break; | |
| default: | |
| abort(); | |
| break; | |
| } | |
| // At this point, everything's go for deletion. The rest of this function | |
| // has to do with non-deletion updates, so we can return. | |
| return; | |
| } | |
| // Okay, this isn't a deletion. In that case, the document's type must in | |
| // the whitelist. | |
| if (!isDeletion) { | |
| enforce(isKnownType(newDoc['type']), 'Invalid type.'); | |
| } | |
| // Also, a document's type cannot change once it has been set. | |
| if (oldDoc) { | |
| enforce(oldDoc['type'] === newDoc['type'], | |
| 'Document types cannot change once they are set.'); | |
| } | |
| // OK, now we know we have a valid type, it hasn't changed, and we're | |
| // updating a document. | |
| // Each type has its own validation rules. We implement them below. | |
| switch (newDoc['type']) { | |
| case 'event': | |
| // A user must be a member to create or update events. | |
| enforce(isMember, 'You must be a site member to add or update events.'); | |
| // If the event already exists, the member must be an organizer of the | |
| // event to change it. | |
| if (oldDoc) { | |
| enforce(userIn(oldDoc['organizers']), | |
| 'You must be an organizer of the event to update it.'); | |
| } | |
| // The member entering the event must take ownership of the event. | |
| enforce(userIn(newDoc['organizers']), | |
| 'You must claim ownership of your event.'); | |
| // The event's name must not be blank. | |
| enforce(notBlank(newDoc['name']), 'Events must have a name.'); | |
| break; | |
| case 'profile': | |
| // A user must be a member to create or update profiles. | |
| enforce(isMember, | |
| 'You must be a site member to add or update profiles.'); | |
| // A member can only update their own profile. | |
| enforce(newDoc['username'] === userCtx.name, | |
| "You cannot edit other editor's profiles."); | |
| break; | |
| case 'source_resolution': | |
| // Only source resolvers may create or update resolution records. | |
| enforce(userHasRole('source_resolver'), | |
| 'Only source resolvers may add or update resolution records.'); | |
| break; | |
| case 'video': | |
| // If the user is a video database admin, skip further checks. | |
| if (userHasRole('video_db_admin')) { | |
| return; | |
| } | |
| // Otherwise, continue with the checks. | |
| // A user must be a member to create or update profiles. | |
| enforce(isMember, | |
| 'You must be a site member to add or update videos.'); | |
| // If the video already exists, the member must be an organizer of the | |
| // video to change it. | |
| if (oldDoc) { | |
| enforce(userIn(oldDoc['owners']), | |
| 'You must be an owner of the video to update it.'); | |
| } | |
| // The member entering the video must take ownership of the video. | |
| enforce(userIn(newDoc['owners']), | |
| 'You must claim ownership of your video.'); | |
| // A video must have a title. | |
| enforce(notBlank(newDoc['title']), 'Videos must have a title.'); | |
| break; | |
| default: | |
| abort(); | |
| break; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment