Search code examples
meteormeteor-autoformsimple-schema

Meteor simpleSchema prevent field updates


Is it possible to specify that a field is not updateable using the schema itself rather than defining it in an allow/deny rule?

I am wondering because I use a quickform to allow users to edit their user details based on the users document (accounts package) and I want to prevent them from being able to change the verified state for their email address.

A rule based on user roles would be great to only allow admins and meteor itself to change the state of this field.

I'd be hoping for something like this:

    emails: {
        type: Array,
        optional: true
    },
    "emails.$": {
        type: Object
    },
    "emails.$.address": {
        type: String,
        regEx: SimpleSchema.RegEx.Email
    },
    "emails.$.verified": {
        type: Boolean
        allowRoles: ['admin','system'] // this does not exist
    },

regards, Chris


Solution

  • You have a few different options.

    To prevent anyone from updating a field, you can set the denyUpdate field in the flag definition (requires aldeed:collection2)

    "emails.$.verified": {
        type: Boolean
        denyUpdate: true
    },
    

    To allow it to be updated by admin's only, you could try a custom validator that checks the userId to see if it is an admin (example requires aldeed:collection2 and alanning:roles)

    "emails.$.verified": {
        type: Boolean
        custom: function() {
          if ( this.isSet && this.isUpdate &&  !Roles.userIsInRole(this.userId, "admin") ) {
            return "unauthorized";
          }
        }
    },
    

    You'd probably also want to define a message for the "unauthorized" validation error.

    SimpleSchema.messages({
       "unauthorized" : "You do not have permission to update this field"
    })
    

    This will display an error to the user if they try to change the field.

    Alternately, you could simply unset the value provided by non-admin users and allow the rest of the update to go ahead.

    "emails.$.verified": {
        type: Boolean
        autoValue: function() {
          if ( !Roles.userIsInRole(this.userId, "admin") ) {
            this.unset();
          }
        }
    },