Start a new topic

_acl.addWriterGroup creating empty array

 Hi,


I'm trying to create a PreSave hook on one of my collections that adds a write and read group to the entity's acl before saving it. However, when the entity is saved the _acl looks like this:


{
  "creator": "56d8f90d0c0dec967121e348",
  "groups": []
}


The interesting thing here is that the "groups" object doesn't follow the format as per the documentation. The documentation states that the _acl should be in the format below.:


# Regular entity with a detailed ACL structure included    
{

"_id" : "4ff99979c0c014af6ee2773b",
"field1" : "value1",
"field2" : "value2",
"field3" : "value3",
"_acl":
{
"creator": "user_id_1",
"gr": true,
"gw": false,
"r": ["user_id_2", "user_id_3"],
"w": ["user_id_4", "user_id_5"],
"groups": {
"r": ["group_id_1", "group_id_5"],
"w": ["group_id_3", "group_id_4"]
}

}
}

You can see that "groups" should be an object with two arrays "r" and "w". Yet when I call myEntity._acl.addWriterGroup('group_id_1'), it creates a "groups" : [] and my group_id_1 is nowhere to be seen.


I'm at a loss as to why it doesn't work. I've tried to manually create the "groups" as an object and then create "r" and "w" as arrays and then push my groupId in to it, but it results in a runtime error saying that it can't parse the JSON in that format. So one of two things is possible:


1. The format has changed and the documentation hasn't been updated

2. There is a bug in the addWriteGroup


Does anybody have any idea?


Thanks


Jacob







Hi Jacob,


Can you share your BL PreSave code? Let me see if I can track the issue for you.



Regards,

Wani

Kinvey Support



Hi Wani

This is the PreSave. I'm only new to Kinvey so please forgive me.

function onPreSave(request, response, modules) {
  var logger = modules.logger;
  var kinvey = modules.kinvey;
  var requestContext = modules.requestContext;
  var collectionAccess = modules.collectionAccess;
 
  var hospital = kinvey.entity(request.body);
 
  var userId = requestContext.getAuthenticatedUserId();
  var collection = collectionAccess.collection('group');
 
  collection.findOne({"_id":userId}, function(err, group) {
    if(err)
    {
      logger.error(err);
    }
    else if(group === null)
    {
      logger.info('group does not exist, so need to create one.');
      var entity = kinvey.entity(userId);
      logger.info('entity = ' + entity._id + ' acl ' + entity._acl);
      collection.insert(entity, function(err, result)
      {
 
      });
    }
   
  
  });
 
  var acl = hospital._acl;
  var wg = acl.getWriterGroups();
  logger.info('wg: ' + wg.length);
 
  if(wg.indexOf(userId) < 0)
  {
    logger.info('Group does not exist in acl, so need to create.');
    hospital._acl.addWriterGroup(userId);
    hospital._acl.addWriterGroup('TestGroup');
   
  }
  else
  {
    logger.info('Group already exists.')
  }
 
  response.continue();
}

 



I'm basically trying to create a user group with the same Id as the user (this will form part of the code which will allow for the user to have delegates to perform actions on entities on their behalf). The code:


hospital._acl.addWriterGroup(userId);
    hospital._acl.addWriterGroup('TestGroup');


runs successfully, but results in the _acl having "groups" : []


Thank you for taking a look.


Jacob

Hi Wani

Further to the information I submitted last night, I have found the following. I'm using KinveyXamarin and the AccessControlList defined by KinveyXamarin looks like this:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace KinveyXamarin
{
[JsonObject]
public class AccessControlList
{
//
// Static Fields
//
public const string JSON_FIELD_NAME = "_acl";

//
// Properties
//
[JsonProperty]
public string creator
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

[JsonProperty("gr")]
public bool globallyReadable
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

[JsonProperty("gw")]
public bool globallyWriteable
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

[JsonProperty("groups")]
public List<AccessControlList.AclGroups> groups
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

[JsonProperty("r")]
public List<string> read
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

[JsonProperty("w")]
public List<string> write
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

//
// Constructors
//
public AccessControlList();

//
// Nested Types
//
[JsonObject]
public class AclGroups
{
[JsonProperty("r")]
public string read
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

[JsonProperty("w")]
public string write
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}

public AclGroups();
}
}
}

The important thing to note is that it defines the property Groups as a list of type AclGroups. AclGroups has two properties a string for read and a string for write. This class structure is not correct according to the documentation. This really should be:

public AclGroups Groups {get; set;}

and then AclGroups should be defined by having a List<string> w and a List<string> r.

This is why I get a deserialization error when I force the BL to save the groups acl in the format as per the documentation:

"groups": {
    "w": [
      "GroupId"
    ]
  }

This proves that either the SDK for Xamarin is incorrect, or the BL _acl.addWriterGroup method is incorrect.

This issue is really affecting my evaluation of Kinvey.

Can you please get back to me with a resolution to this issue?

Thanks

Jacob


 

Hello Jacob,


I am sorry that this feature isn't working for you, however you have run into a non-working piece of business logic.  More unfortunately, this part of our implementation of groups is not going to be fixed and will be addressed in an overhaul to groups which is at least a few months away at this time.  


I apologize for the inconvenience that this causes you, but for now the best way to manage this is to add individual users to the _acl field rather than using the implementation of groups.  


Thanks,

Hi Damien

Thanks for looking into this for me. That really is unfortunate. Interestingly, I seem to have got groups working for me. I ended up changing my BL to add to the groups manually like so:

entity._acl.groups = entity._acl.groups || {};
  entity._acl.groups.w = entity._acl.groups.w || [];
  entity._acl.groups.r = entity._acl.groups.r || [];
 
  if(entity._acl.groups.r.indexOf(groupId) === -1)
  {
    entity._acl.groups.r.push(groupId);
  }
 
  if(entity._acl.groups.w.indexOf(groupId) === -1)
  {
    entity._acl.groups.w.push(groupId);
  }

Then I created my own AccessControlList class using KinveyXamarin that implements groups in the format as per the documentation.

[JsonObject]
public class AccessControlListCustom
{
//
// Static Fields
//
public const string JSON_FIELD_NAME = "_acl";

//
// Properties
//
[JsonProperty]
public string creator
{

get;

set;
}

[JsonProperty("gr")]
public bool globallyReadable
{

get;

set;
}

[JsonProperty("gw")]
public bool globallyWriteable
{

get;

set;
}

[JsonProperty("groups")]
public AccessControlListCustom.AclGroups groups
{

get;

set;
}

[JsonProperty("r")]
public List<string> read
{

get;

set;
}

[JsonProperty("w")]
public List<string> write
{

get;

set;
}

//
// Constructors
//
public AccessControlListCustom() {}

//
// Nested Types
//
[JsonObject]
public class AclGroups
{
[JsonProperty("r")]
public List<string> read
{

get;

set;
}

[JsonProperty("w")]
public List<string> write
{

get;

set;
}

public AclGroups() {}
}
}

These two changes are all I had to do. It looks like the rest of the internal Kinvey logic is working. Using individuals rather than groups is a bit untenable. If UserA stops being a delegate for UserB, then I need to remove UserA from every entity that UserB created. This is far from ideal obviously. Should I just continue down my custom path until such time as Kinvey groups are fixed? Or is it something that is likely to break soon? Are there any other "non-working pieces of business logic" that I should be aware of as I continue down the evaluation path?

Cheers

Jacob

 

The path that you are using now should continue to work indefinitely.  In the event that we are going to make any changes to groups going forward, we would either version it at the API level, or we would soft deprecate the existing version of things.    We try VERY hard not to break legacy code here at Kinvey, because some of the apps running on us are made by development firms and are sold to the (now) owners.  Us breaking their code would cost them in downtime and further development costs, and we're very sensitive to that.


In the event that breaking changes are going to be made, we announce them as early as possible.  


Thanks,

Thanks Damien, I appreciate you clarifying things. I will continue to work on the proof of concept for our new product. Hopefully, things will go a bit smoother from here on. It gives me comfort that support is available.

Thanks again

Jacob

 

Login or Signup to post a comment