vsivsi / meteor-file-collection

Extends Meteor Collections to handle file data using MongoDB gridFS.
http://atmospherejs.com/vsivsi/file-collection
Other
159 stars 37 forks source link

403 forbidden when using a method #139

Closed hamedhemmati closed 7 years ago

hamedhemmati commented 7 years ago

This is more of a question than an issue. I am trying to use a meteor method instead of allowing client side insert. I think I have everything done correctly but I am getting a 403 forbidden on the resumable upload.

On the client I have

r.on('fileAdded', function (file) {
        Session.set(file.uniqueIdentifier, 0);
        Meteor.call('updateAvatar', file.uniqueIdentifier, file.fileName, file.file.type, function (error, _id) {
            if (error) { return console.log("File creation failed!", error); }
            r.upload();
        });
    });

and on the server I have this method

Meteor.methods({
    'updateAvatar'(uniqueIdentifier, fileName, fileType){
        return Avatars.insert({
            _id: uniqueIdentifier,  // This is the ID resumable will use
            filename: fileName,
            contentType: fileType
        });
    }
});

There seems to be a permission problem for uploading the chunks.

vsivsi commented 7 years ago

Have you written an appropriate "allow rule" for file 'write' permission?

See docs: https://github.com/vsivsi/meteor-file-collection#fcallowoptions

Also, sample app code: https://github.com/vsivsi/meteor-file-sample-app/blob/master/sample.coffee#L192-L197

hamedhemmati commented 7 years ago

Yes I have all the allow rules based on the documentation. If I switch the meteor.call to a client side insert then it works fine.

These are the rules I have on the server and I wanted to get rid of the insert and remove for security reasons by using a method.

Meteor.publish('myAvatar',
    function (clientUserId) {
        if (clientUserId === this.userId) {
            return Avatars.find({ 'metadata._Resumable': { $exists: false },
                'metadata.owner': this.userId });
        } else {        // Prevent client race condition:
            return null;  // This is triggered when publish is rerun with a new
                          // userId before client has resubscribed with that userId
        }
    }
);

// Allow rules for security. Should look familiar!
// Without these, no file writes would be allowed
Avatars.allow({
    // The creator of a file owns it. UserId may be null.
    insert: function (userId, file) {
        // Assign the proper owner when a file is created
        file.metadata = file.metadata || {};
        file.metadata.owner = userId;
        return true;
    },
    // Only owners can remove a file
    remove: function (userId, file) {
        // Only owners can delete
        return (userId === file.metadata.owner);
    },
    // Only owners can retrieve a file via HTTP GET
    read: function (userId, file) {
        return (userId === file.metadata.owner);
    },
    // This rule secures the HTTP REST interfaces' PUT/POST
    // Necessary to support Resumable.js
    write: function (userId, file, fields) {
        // Only owners can upload file data
        return (userId === file.metadata.owner);
    }
});
vsivsi commented 7 years ago

And does your "insert method" properly set the file.metadata.owner property on the new file? The insert allow rule will not be triggered on a server-side insert, so you'll need to handle that in your method.

hamedhemmati commented 7 years ago

I see so the owner wasn't set. I just added

metadata: {
                owner: this.userId
            }

to my method and now it's working fine. Thanks for the help and the awesome package!