| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 | 
							- var path = Npm.require("path");
 
- HTTP.publishFormats({
 
-   fileRecordFormat: function (input) {
 
-     // Set the method scope content type to json
 
-     this.setContentType('application/json');
 
-     if (FS.Utility.isArray(input)) {
 
-       return EJSON.stringify(FS.Utility.map(input, function (obj) {
 
-         return FS.Utility.cloneFileRecord(obj);
 
-       }));
 
-     } else {
 
-       return EJSON.stringify(FS.Utility.cloneFileRecord(input));
 
-     }
 
-   }
 
- });
 
- /**
 
-  * @method FS.HTTP.setHeadersForGet
 
-  * @public
 
-  * @param {Array} headers - List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value.
 
-  * @param {Array|String} [collections] - Which collections the headers should be added for. Omit this argument to add the header for all collections.
 
-  * @returns {undefined}
 
-  */
 
- FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) {
 
-   if (typeof collections === "string") {
 
-     collections = [collections];
 
-   }
 
-   if (collections) {
 
-     FS.Utility.each(collections, function(collectionName) {
 
-       getHeadersByCollection[collectionName] = headers || [];
 
-     });
 
-   } else {
 
-     getHeaders = headers || [];
 
-   }
 
- };
 
- /**
 
-  * @method FS.HTTP.publish
 
-  * @public
 
-  * @param {FS.Collection} collection
 
-  * @param {Function} func - Publish function that returns a cursor.
 
-  * @returns {undefined}
 
-  *
 
-  * Publishes all documents returned by the cursor at a GET URL
 
-  * with the format baseUrl/record/collectionName. The publish
 
-  * function `this` is similar to normal `Meteor.publish`.
 
-  */
 
- FS.HTTP.publish = function fsHttpPublish(collection, func) {
 
-   var name = baseUrl + '/record/' + collection.name;
 
-   // Mount collection listing URL using http-publish package
 
-   HTTP.publish({
 
-     name: name,
 
-     defaultFormat: 'fileRecordFormat',
 
-     collection: collection,
 
-     collectionGet: true,
 
-     collectionPost: false,
 
-     documentGet: true,
 
-     documentPut: false,
 
-     documentDelete: false
 
-   }, func);
 
-   FS.debug && console.log("Registered HTTP method GET URLs:\n\n" + name + '\n' + name + '/:id\n');
 
- };
 
- /**
 
-  * @method FS.HTTP.unpublish
 
-  * @public
 
-  * @param {FS.Collection} collection
 
-  * @returns {undefined}
 
-  *
 
-  * Unpublishes a restpoint created by a call to `FS.HTTP.publish`
 
-  */
 
- FS.HTTP.unpublish = function fsHttpUnpublish(collection) {
 
-   // Mount collection listing URL using http-publish package
 
-   HTTP.unpublish(baseUrl + '/record/' + collection.name);
 
- };
 
- _existingMountPoints = {};
 
- /**
 
-  * @method defaultSelectorFunction
 
-  * @private
 
-  * @returns { collection, file }
 
-  *
 
-  * This is the default selector function
 
-  */
 
- var defaultSelectorFunction = function() {
 
-   var self = this;
 
-   // Selector function
 
-   //
 
-   // This function will have to return the collection and the
 
-   // file. If file not found undefined is returned - if null is returned the
 
-   // search was not possible
 
-   var opts = FS.Utility.extend({}, self.query || {}, self.params || {});
 
-   // Get the collection name from the url
 
-   var collectionName = opts.collectionName;
 
-   // Get the id from the url
 
-   var id = opts.id;
 
-   // Get the collection
 
-   var collection = FS._collections[collectionName];
 
-   //if Mongo ObjectIds are used, then we need to use that in find statement
 
-   if(collection.options.idGeneration && collection.options.idGeneration === 'MONGO') {
 
-     // Get the file if possible else return null
 
-     var file = (id && collection)? collection.findOne({ _id: new Meteor.Collection.ObjectID(id)}): null;
 
-   } else {
 
-     var file = (id && collection)? collection.findOne({ _id: id }): null;
 
-   }
 
-   // Return the collection and the file
 
-   return {
 
-     collection: collection,
 
-     file: file,
 
-     storeName: opts.store,
 
-     download: opts.download,
 
-     filename: opts.filename
 
-   };
 
- };
 
- /*
 
-  * @method FS.HTTP.mount
 
-  * @public
 
-  * @param {array of string} mountPoints mount points to map rest functinality on
 
-  * @param {function} selector_f [selector] function returns `{ collection, file }` for mount points to work with
 
-  *
 
- */
 
- FS.HTTP.mount = function(mountPoints, selector_f) {
 
-   // We take mount points as an array and we get a selector function
 
-   var selectorFunction = selector_f || defaultSelectorFunction;
 
-   var accessPoint = {
 
-     'stream': true,
 
-     'auth': expirationAuth,
 
-     'post': function(data) {
 
-       // Use the selector for finding the collection and file reference
 
-       var ref = selectorFunction.call(this);
 
-       // We dont support post - this would be normal insert eg. of filerecord?
 
-       throw new Meteor.Error(501, "Not implemented", "Post is not supported");
 
-     },
 
-     'put': function(data) {
 
-       // Use the selector for finding the collection and file reference
 
-       var ref = selectorFunction.call(this);
 
-       // Make sure we have a collection reference
 
-       if (!ref.collection)
 
-         throw new Meteor.Error(404, "Not Found", "No collection found");
 
-       // Make sure we have a file reference
 
-       if (ref.file === null) {
 
-         // No id supplied so we will create a new FS.File instance and
 
-         // insert the supplied data.
 
-         return FS.HTTP.Handlers.PutInsert.apply(this, [ref]);
 
-       } else {
 
-         if (ref.file) {
 
-           return FS.HTTP.Handlers.PutUpdate.apply(this, [ref]);
 
-         } else {
 
-           throw new Meteor.Error(404, "Not Found", 'No file found');
 
-         }
 
-       }
 
-     },
 
-     'get': function(data) {
 
-       // Use the selector for finding the collection and file reference
 
-       var ref = selectorFunction.call(this);
 
-       // Make sure we have a collection reference
 
-       if (!ref.collection)
 
-         throw new Meteor.Error(404, "Not Found", "No collection found");
 
-       // Make sure we have a file reference
 
-       if (ref.file === null) {
 
-         // No id supplied so we will return the published list of files ala
 
-         // http.publish in json format
 
-         return FS.HTTP.Handlers.GetList.apply(this, [ref]);
 
-       } else {
 
-         if (ref.file) {
 
-           return FS.HTTP.Handlers.Get.apply(this, [ref]);
 
-         } else {
 
-           throw new Meteor.Error(404, "Not Found", 'No file found');
 
-         }
 
-       }
 
-     },
 
-     'delete': function(data) {
 
-       // Use the selector for finding the collection and file reference
 
-       var ref = selectorFunction.call(this);
 
-       // Make sure we have a collection reference
 
-       if (!ref.collection)
 
-         throw new Meteor.Error(404, "Not Found", "No collection found");
 
-       // Make sure we have a file reference
 
-       if (ref.file) {
 
-         return FS.HTTP.Handlers.Del.apply(this, [ref]);
 
-       } else {
 
-         throw new Meteor.Error(404, "Not Found", 'No file found');
 
-       }
 
-     }
 
-   };
 
-   var accessPoints = {};
 
-   // Add debug message
 
-   FS.debug && console.log('Registered HTTP method URLs:');
 
-   FS.Utility.each(mountPoints, function(mountPoint) {
 
-     // Couple mountpoint and accesspoint
 
-     accessPoints[mountPoint] = accessPoint;
 
-     // Remember our mountpoints
 
-     _existingMountPoints[mountPoint] = mountPoint;
 
-     // Add debug message
 
-     FS.debug && console.log(mountPoint);
 
-   });
 
-   // XXX: HTTP:methods should unmount existing mounts in case of overwriting?
 
-   HTTP.methods(accessPoints);
 
- };
 
- /**
 
-  * @method FS.HTTP.unmount
 
-  * @public
 
-  * @param {string | array of string} [mountPoints] Optional, if not specified all mountpoints are unmounted
 
-  *
 
-  */
 
- FS.HTTP.unmount = function(mountPoints) {
 
-   // The mountPoints is optional, can be string or array if undefined then
 
-   // _existingMountPoints will be used
 
-   var unmountList;
 
-   // Container for the mount points to unmount
 
-   var unmountPoints = {};
 
-   if (typeof mountPoints === 'undefined') {
 
-     // Use existing mount points - unmount all
 
-     unmountList = _existingMountPoints;
 
-   } else if (mountPoints === ''+mountPoints) {
 
-     // Got a string
 
-     unmountList = [mountPoints];
 
-   } else if (mountPoints.length) {
 
-     // Got an array
 
-     unmountList = mountPoints;
 
-   }
 
-   // If we have a list to unmount
 
-   if (unmountList) {
 
-     // Iterate over each item
 
-     FS.Utility.each(unmountList, function(mountPoint) {
 
-       // Check _existingMountPoints to make sure the mount point exists in our
 
-       // context / was created by the FS.HTTP.mount
 
-       if (_existingMountPoints[mountPoint]) {
 
-         // Mark as unmount
 
-         unmountPoints[mountPoint] = false;
 
-         // Release
 
-         delete _existingMountPoints[mountPoint];
 
-       }
 
-     });
 
-     FS.debug && console.log('FS.HTTP.unmount:');
 
-     FS.debug && console.log(unmountPoints);
 
-     // Complete unmount
 
-     HTTP.methods(unmountPoints);
 
-   }
 
- };
 
- // ### FS.Collection maps on HTTP pr. default on the following restpoints:
 
- // *
 
- //    baseUrl + '/files/:collectionName/:id/:filename',
 
- //    baseUrl + '/files/:collectionName/:id',
 
- //    baseUrl + '/files/:collectionName'
 
- //
 
- // Change/ replace the existing mount point by:
 
- // ```js
 
- //   // unmount all existing
 
- //   FS.HTTP.unmount();
 
- //   // Create new mount point
 
- //   FS.HTTP.mount([
 
- //    '/cfs/files/:collectionName/:id/:filename',
 
- //    '/cfs/files/:collectionName/:id',
 
- //    '/cfs/files/:collectionName'
 
- //  ]);
 
- //  ```
 
- //
 
- mountUrls = function mountUrls() {
 
-   // We unmount first in case we are calling this a second time
 
-   FS.HTTP.unmount();
 
-   FS.HTTP.mount([
 
-     baseUrl + '/files/:collectionName/:id/:filename',
 
-     baseUrl + '/files/:collectionName/:id',
 
-     baseUrl + '/files/:collectionName'
 
-   ]);
 
- };
 
- // Returns the userId from URL token
 
- var expirationAuth = function expirationAuth() {
 
-   var self = this;
 
-   // Read the token from '/hello?token=base64'
 
-   var encodedToken = self.query.token;
 
-   FS.debug && console.log("token: "+encodedToken);
 
-   if (!encodedToken || !Meteor.users) return false;
 
-   // Check the userToken before adding it to the db query
 
-   // Set the this.userId
 
-   var tokenString = FS.Utility.atob(encodedToken);
 
-   var tokenObject;
 
-   try {
 
-     tokenObject = JSON.parse(tokenString);
 
-   } catch(err) {
 
-     throw new Meteor.Error(400, 'Bad Request');
 
-   }
 
-   // XXX: Do some check here of the object
 
-   var userToken = tokenObject.authToken;
 
-   if (userToken !== ''+userToken) {
 
-     throw new Meteor.Error(400, 'Bad Request');
 
-   }
 
-   // If we have an expiration token we should check that it's still valid
 
-   if (tokenObject.expiration != null) {
 
-     // check if its too old
 
-     var now = Date.now();
 
-     if (tokenObject.expiration < now) {
 
-       FS.debug && console.log('Expired token: ' + tokenObject.expiration + ' is less than ' + now);
 
-       throw new Meteor.Error(500, 'Expired token');
 
-     }
 
-   }
 
-   // We are not on a secure line - so we have to look up the user...
 
-   var user = Meteor.users.findOne({
 
-     $or: [
 
-       {'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(userToken)},
 
-       {'services.resume.loginTokens.token': userToken}
 
-     ]
 
-   });
 
-   // Set the userId in the scope
 
-   return user && user._id;
 
- };
 
- HTTP.methods(
 
-   {'/cfs/servertime': {
 
-     get: function(data) {
 
-       return Date.now().toString();
 
-     }
 
-   }
 
- });
 
- // Unify client / server api
 
- FS.HTTP.now = function() {
 
-   return Date.now();
 
- };
 
- // Start up the basic mount points
 
- Meteor.startup(function () {
 
-   mountUrls();
 
- });
 
 
  |