Search code examples
meteor

How to deny user.profile's update on login?


On my user profile schema, I have a field called "actu" like this:

Actu: {
 type: Date,
    autoValue: function() {
        if ( this.isUpdate ) {
            return new Date;
        } 
    }
}

If I restart Meteor, this field is not updated. Which is fine for me. But when I log in my account, the field is automatically updated. Which is wrong for me - you get it...

In few words, I'd like this field being updated only on the update of the collection (by autoform - this works great).

Any idea? Any Obi Wan Kenobi to help me?

EDIT// Here's my Query and my full schema

//Query

{{#autoForm collection='Meteor.users' doc=currentUser type='update' id='accountForm'}}
<span>phone</span> {{> afFieldInput name='profile.phone'}}<br>
<span>avatar</span> {{> afFieldInput name='profile.avatar'}}
<button type='submit' class="at-btn dark">Update</button>
{{/autoForm}}

//Full Schema

            import SimpleSchema from 'simpl-schema';

            Schema = {};

            Schema.UserProfile = new SimpleSchema({
                phone: {
                    type: String,
                    label: "Phone of user"
                    //denyUpdate: true
                },
                avatar: {
                    type: String,
                    label: "User core actualization function"
                },
                Actu: {
                    type: Date,
                    autoValue: function() {
                        if ( this.field('phone').isSet ) {
                        return new Date;
                        }
                    }
                }
            });

            Schema.User = new SimpleSchema({
                username: {
                    type: String,
                    // For accounts-password, either emails or username is required, but not both. It is OK to make this
                    // optional here because the accounts-password package does its own validation.
                    // Third-party login packages may not require either. Adjust this schema as necessary for your usage.
                    optional: true
                },
                emails: {
                    type: Array,
                    // For accounts-password, either emails or username is required, but not both. It is OK to make this
                    // optional here because the accounts-password package does its own validation.
                    // Third-party login packages may not require either. Adjust this schema as necessary for your usage.
                },
                "emails.$": {
                    type: Object
                },
                "emails.$.address": {
                    type: String,
                    regEx: SimpleSchema.RegEx.Email
                },
                "emails.$.verified": {
                    type: Boolean
                },
                // Management of the 2FA Code
                twoFactorCode: {
                    type: String,
                    regEx: /^[0-9]{6}$/,
                    optional: true
                },
                createdAt: {
                    type: Date
                },
                profile: {
                    type: Schema.UserProfile,
                    optional: true
                },
                // Make sure this services field is in your schema if you're using any of the accounts packages
                services: {
                    type: Object,
                    optional: true,
                    blackbox: true
                },
                // Add `roles` to your schema if you use the meteor-roles package.
                // Option 1: Object type
                // If you specify that type as Object, you must also specify the
                // `Roles.GLOBAL_GROUP` group whenever you add a user to a role.
                // Example:
                // Roles.addUsersToRoles(userId, ["admin"], Roles.GLOBAL_GROUP);
                // You can't mix and match adding with and without a group since
                // you will fail validation in some cases.
                roles: {
                    type: Object,
                    optional: true,
                    blackbox: true
                },
                'roles.$': {
                    type: String
                },
                // In order to avoid an 'Exception in setInterval callback' from Meteor
                heartbeat: {
                    type: Date,
                    optional: true
                }
            });

            Meteor.users.attachSchema(Schema.User);

Solution

  • To supplement Michael's answer, in light of your edit:

    You are defining your profile schema as a sub-schema, and therefore it has no knowledge of itself being used as the profile property of the user's schema.

    This is a great use-case for choosing siblingField over field, as field should denote an "absolute" field name within the main schema.

    You can update the autoValue field iff any of the "trigger" sibling fields is set using something in the lines of:

    Actu: {
        type: Date,
        autoValue: function () {
            const triggerFields = ['phone', 'avatar'];
            let shouldTrigger =
                triggerFields.findIndex(f => this.siblingField(f).isSet) !== -1;
    
            if (shouldTrigger) {
                return new Date();
            }
        },
    }
    

    Note:

    It is possible to use field(), but it is less flexible as you should specify it using an absolute notation, e.g, phone should be specified as profile.phone, which means that you can only use it as a sub-schema for a field called profile if you want it to work.