Creating pointers on user.signUp

Hi all,

I was looking for some suggestions re. creating pointers on user.signUp via cloud code.

My problem is that as request.object (i.e request.user because it’s a trigger on beforeSave) has no objectId, so I can’t set ACLs for my pointer.

If I use it on afterSave, the trigger resolves before pointer.save is set.

Here’s my code:

const user = new Parse.User();
user.set('businessName','xx');
await user.signUp();
// I want to be able to call user.get('business') here and it be a pointer with ACLs set.
...

cloud:

// I can't user beforeSave because object.id isn't defined on new objects, so I can't set ACL for business object
Parse.Cloud.afterSave(Parse.User, async ({object}) => {
  if (!object.existed()) {
    const acl = new Parse.ACL(object);
    object.setACL(acl);
    const business = new Parse.Object('Business');
    business.set('name',object.get('businessName'));
    object.unset('businessName');
    business.set('admin',object);

    const businessACL = new Parse.ACL(object);
    business.setACL(businessACL);
    await business.save(null,{useMasterKey:true});
    object.set('business',business);
  }

});

I know that I can do it on the frontend, but I’m trying to keep my SDK code as simple and clean as possible.

I believe that await object.save(null, { useMasterKey: true }); return object; at the end of your afterSave trigger should do the magic, not?

Thanks for the response! This has no affect on the object on the frontend. Even when I add the code you specify, the object returned from signup / user.get('business') is still null.

That’s strange. I believe it should be returned. Would you mind to share your current code so I can also try to test in my side?

Frontend:

it('register', async () => {
    const user = new Parse.User();
    user.set('username', '[email protected]');
    user.set('businessName','Test Business');
    user.set('password','password');
    user.set('businessPhone','+614TESTPHONE');
    await user.signUp();
    const current = user;
    expect(current).toBeDefined();
    expect(current.get('username')).toBe('[email protected]');
    expect(current.get('email')).toBe('[email protected]');
    expect(current.get('password')).toBeUndefined();
    const business = current.get('business');
    expect(business).toBeDefined();
    expect(business.get('name')).toBe('Test Business');
    expect(business.get('profile')).toBe('testbusiness');
    expect(business.get('phone')).toBe('Test Business');
    expect(business.get('admin').id).toBe(current.id);

    // check security
    const userAcl = current.getACL().toJSON();
    expect(userAcl['*']).toBeUndefined();

    const businessAcl = current.get('business').getACL().toJSON();
    expect(businessAcl['*']).toBeDefined();
    expect(businessAcl['*']['read']).toBe(true);
    expect(businessAcl['*']['write']).not.toBe(true);
  });

Cloud:

Parse.Cloud.afterSave(Parse.User, async ({object}) => {
  if (!object.existed()) {
    const business = new Parse.Object('Business');
    business.set('name',object.get('businessName'));
    business.set('profile',object.get('businessName').split(' ').join(' ').toLowerCase());
    business.set('phone',object.get('businessPhone'));
    business.set('invoices',0);
    business.set('admin',object);
    const businessACL = new Parse.ACL();
    business.setACL(businessACL);
    object.unset('businessName');
    object.unset('businessPhone');
    await business.save(null,{useMasterKey:true});
    businessACL.setRoleReadAccess(business.id, true);
    businessACL.setWriteAccess(object.id, true);
    business.setACL(businessACL);
    object.set('business',business);
    const businessRole = new Parse.Role(business.id);
    const roleACL = new Parse.ACL(object);
    roleACL.setPublicReadAccess(true);
    businessRole.setACL(roleACL);
    businessRole.getUsers().add(object);
    await Parse.Object.saveAll([businessRole,business,object],{useMasterKey:true});
  }
  return object;
}, {
  skipWithMasterKey:true
});

Which line in the test case fails? I believe everything should work but probably not:

expect(business.get('name')).toBe('Test Business');
expect(business.get('profile')).toBe('testbusiness');
expect(business.get('phone')).toBe('Test Business');
expect(business.get('admin').id).toBe(current.id);

I am not sure the pointer fields will be included, but it should be defined and having an id. Would you mind to also test using the REST API? Maybe it is somethinng in the JS SDK.

@davimacedo you were right, the beforeSave trigger for the Business class was preventing save of the object, so the return statment was never called. Thank you!

You’re welcome. I’m glad you’ve figured it out.