Record Level Security and Custom Fields

Scenario:

I have a record like below:

Container Record which has fields like id, caseId, claimsId, providerId and these 3 fields point to primary keys of 3 other records Case, Claim and Provider.

Whenever an entry is made in Case an associated entry is made in Container for fields id and caseId

Whenever an entry is made in Claim an associated entry is made in Container for fields id and claimId

Whenever an entry is made in Provider an associated entry is made in Container for fields id and providerId

At any point there would be only 2 column in Container which would have values.

On Container we also have added custom fields to fetch other data fields like summary from Case, Claim, Provider and each of these 3 records have summary field

We are using realtime custom field using customfieldmatch to decide which related record should be used to get the summary field for the custom field by looking at which identifier is not null.

a!customFieldMatch(
  value: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.fields.{8c51d2ea-b8f6-420c-a2a1-1f0b6fbce346}containerId',
  whenTrue: a!customFieldCondition(
    field: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.fields.{ae24d835-8cac-42f7-b192-394a6ad713e1}crtStandardFieldsId',
    operator: "not null"
  ),
  then: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.relationships.{f9cefa68-b1db-42a0-b041-737f6643253c}crt.fields.{e1e6480f-e6a2-4169-bd05-0a538ec0f604}createdDt',
  whenTrue: a!customFieldCondition(
    field: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.fields.{718d97c1-228f-4779-9a51-f300280bb237}clmRequestId',
    operator: "not null"
  ),
  then: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.relationships.{cf544733-65d7-46c6-82fb-fd9ca0965581}clm.fields.{fb041636-a610-4ba7-b8a0-81efb5a68a4b}createdDt',
  whenTrue: a!customFieldCondition(
    field: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.fields.{c192123a-53a8-4aec-99f5-3d0ba3787ec8}caseId',
    operator: "not null"
  ),
  then: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.relationships.{39e703a6-3cbd-420e-aae2-c8c6c9d3f467}case.fields.{a8665c5a-25d9-43a0-a792-f56bfb0d9ad5}createdDt',
  whenTrue: a!customFieldCondition(
    field: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.fields.{08f3427f-cba9-4039-879b-81c30ef112a9}ppoRequestId',
    operator: "not null"
  ),
  then: 'recordType!{6453c614-aa7e-4b62-bc94-364fa1539a31}OPS Container.relationships.{714676ca-f05d-4d0d-8389-f84ea7c1903f}ppo.fields.{790fa23a-6fe7-4bf3-9f3b-cae34c27037d}createdDt',
  default: today(),
)

Now we also have different set of users who have access to each of these 3 apps Case, Claim, Provider and hence we added record level security to control who would see what records.

All seems ok, but when we use this inside grid and a user who is only having access to some of these apps and not all 3 apps, they are not able to see any data for summary.

But if instead of using the customField, we take the same code and put it on interface gridColumn, the data seem to be coming along fine for whatever record user has access for.

Is there any difference how custom fields are evaluated?

I know it's long shot and not everyday problem, any experience/insight around this is appreciated

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    I do not see any certifications on your profile. How much experience do you have?

    On which record do you apply security? I ask, because Appian applies security rules at the lowest possible level. This means, before it evaluates your custom fields. If you rely on non-accessible data, this will fail.

  • This is not my primary profile! rest assured!

    Record level security is applied to the Container record to control only records visible to the users should be the one they have access, eg. if user has access to Case record, they should only see container record that is related to Case and so on!

  • 0
    Certified Lead Developer
    in reply to ambrishs2768

    I am just asking to have an idea how much detailed guidance you might need.

    Did you try to query the data outside of a grid? When using different accounts, I would expect to see the same behaviour. I think it is important to get the grid out of the game.

    Do you see any errors in log files?

    Is the problem with the custom record field, or the security rules? From your description, I understand that when removing the custom field, things work as expected. Is that correct?

  • Did you try to query the data outside of a grid? When using different accounts, I would expect to see the same behaviour. I think it is important to get the grid out of the game.- Screenshot shared and same behavior outside grid

    Do you see any errors in log files? No errors

    Is the problem with the custom record field, or the security rules? From your description, I understand that when removing the custom field, things work as expected. Is that correct? - Record field: When the record field is there but the definition is changed to not use a record for which user doesn't have access then data shows up. Example below(Ticket Type (doesn't show up), categoryId (show up).

    So here is the observation which affirms that it's something special with custom fields with record security.

    When queried the data in designer (background screen) it does get data for the custom fields for the record for which the end user(front screen/private mode screen) doesn't have access for some record, but it just refuses to get that data for any of the record. 

    Field on this record is ticketType

    Also can be observed that another field categoryId, it does show the value even for the end user, and reason is that in the custom field definition the record type(CRT) is not configured in the field definition, hence it does bring that data

  • 0
    Certified Lead Developer
    in reply to ambrishs2768

    That is a really difficult situation. In general, if a user does not have permission to access data, then Appian will never allow that.

      , can you help us with some insights on how record security impacts custom record fields? In the last screenshot, I see this cascade of default values. What happens when a user has no access to a value?

  • I also have tried this way of writing the custom field, but still no luck. So idea was whatever record row user has access to, they would be able to find the field values, but looks like Appian just refuses to return the values.. however it works perfect if you just do the same operation for each row inside a grid instead of doing it in the custom Field.  

  • 0
    Appian Employee
    in reply to ambrishs2768

    Can you try checking to see if the relationship is null instead of looking at the field? I have a hunch that the reason it appears to work when running this in the grid column directly is that you're getting the data after the query runs for each column, so null or not visible due to security essentially act the same. However, the custom record field does the calculation in the query (and not after the results are returned), so it treats null and not visible differently.

Reply
  • 0
    Appian Employee
    in reply to ambrishs2768

    Can you try checking to see if the relationship is null instead of looking at the field? I have a hunch that the reason it appears to work when running this in the grid column directly is that you're getting the data after the query runs for each column, so null or not visible due to security essentially act the same. However, the custom record field does the calculation in the query (and not after the results are returned), so it treats null and not visible differently.

Children
  • In this example below, let's say there is only 1 record in the table and the containerId is 388 and the logged in user has access to OPS Container record type as well as related record PPO and hence the user is able to see the date coming from OPSContainer.ppo.createdDt and this is all good when you comment out the other conditions below line 4.

    But if you keep all the logic as shown below and the user doesn't have access to some of those record types below, the createdDt doesn't show up at all.

    It appears to me is that Appian is evaluating all the definition and if any record type in the definition isn't available to the user irrespective of written logic, null is returned which is odd!