Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    includeFrom and declarative security

    Hello, I have a question about includeFrom and declarative security.
    Consider this scenario:
    - DataSource dsA has a default fetch operationBinding with requiresRole="Role_A"
    - DataSource dsB has a default fetch operationBinding with requiresRole="Role_B"
    - dsB has a field <field name="foo_B" includeFrom="dsA.foo_A"/> included from dsA

    Now, the default fetch of dsB will not work unless the user has both Role_A and Role_B.

    This makes sense (even though I couldn't find it clearly stated in the documentation).

    Here's my question: is there a way to allow the default fetch of dsB to work even if the user only has Role_B?
    So far I’ve tried setting viewRequiresRole="" on the included field foo_A in dsA, and viewRequiresRole="Role_B" on the foo_B field in dsB, but neither approach seems to work.

    Since this kind of setup introduces a strong dependency between roles and DataSources, I think it would be useful to have a way to explicitly define this behaviour. What do you think?
    Last edited by claudiobosticco; 17 Apr 2025, 06:24.

    #2
    It appears there is a typo or "thinko" in your question somewhere. The default fetch on dsB will in fact work if the user has Role_B, with the declarations you've shown.

    You must instead mean that you want the includeFrom in dsA from dsB to work despite the user not having access to dsB at all. This should not and does not work, and setting viewRequiresRole cannot be the approach either, since this controls access to the field whereas you hope to provide special access to an entire related DataSource.

    There are a number of ways to make this work:

    1. mark the request as not client-initiated, which turns off all of Declarative Security (so you'd have to check everything else yourself)

    2. make a variant of dsB that only has the single desired field but is accessible by Role_A, and include from that. Or equivalently, make dsB accessible by Role_A, but just mark the fields that Role_A should not see as accessible only by other roles.

    3. some kind of new framework property that says "for this includeFrom field, ignore all security constraints". We probably wouldn't accept this even as a Feature Sponsorship because it's basically a convenience property which would complicate the code a lot, and it would be rare occurrence for a developer to realize the property was there and use it.

    Comment


      #3
      Hello, sorry for not including a working sample from the beginning.

      Here’s the use case I was referring to, which triggers the following exception when a user with only ROLE_B (and without ROLE_A) performs a fetch on ds_B:

      Code:
      java.lang.SecurityException: Security check on related DataSource 'ds_A', required for included field 'pk_A', failed.  Failure message is: "DataSource 'ds_A', operationType 'fetch', operationId 'ds_B_fetch'.  This operation requires role(s) 'ROLE_A'. User 'me@myCompany.com' fails the role check."
      It involves the following two DataSources:

      Code:
      <DataSource xmlns="http://www.smartclient.com/schema"
                  ID="ds_A"
                  schema="mySchema"
                  dbName="myDB"
                  tableName="ds_A"
                  serverType="sql"
      >
          <fields>
              <field name="pk_A" type="integer" primaryKey="true"/>
              <field name="foo_A"/>
      <!-- many other fields...-->
          </fields>
          <operationBindings>
              <operationBinding operationType="fetch" requiresRole="ROLE_A"/>
          </operationBindings>
      </DataSource>
      
      <DataSource xmlns="http://www.smartclient.com/schema"
                  ID="ds_B"
                  schema="mySchema"
                  dbName="myDB"
                  tableName="ds_B"
                  serverType="sql"
      >
          <fields>
              <field name="pk_B" type="integer" primaryKey="true"/>
              <field name="fk_B" type="integer" foreignKey="ds_A.pk_A"/>
              <field name="foo_B" includeFrom="ds_A.foo_A" includeVia="fk_B"/>
      <!-- many other fields...-->
          </fields>
          <operationBindings>
              <operationBinding operationType="fetch" requiresRole="ROLE_B"/>
          </operationBindings>
      </DataSource>
      Now, your explanation still applies, right?

      I was just hoping that by adding viewRequiresRole="ROLE_A,ROLE_B" to the relevant fields in ds_A, like this:

      Code:
      <DataSource xmlns="http://www.smartclient.com/schema"
                  ID="ds_A"
                  schema="mySchema"
                  dbName="myDB"
                  tableName="ds_A"
                  serverType="sql"
      >
          <fields>
              <field name="pk_A" type="integer" primaryKey="true" viewRequiresRole="ROLE_A,ROLE_B"/>
              <field name="foo_A" viewRequiresRole="ROLE_A,ROLE_B"/>
          </fields>
          <operationBindings>
              <operationBinding operationType="fetch" requiresRole="ROLE_A"/>
          </operationBindings>
      </DataSource>
      ...the framework would allow ds_B to include them for a user who has ROLE_B.

      Wouldn't it make sense to allow this kind of access when the included fields explicitly declare viewRequiresRole, and the user has the required role(s)?

      This approach wouldn't seem to conflict with the existing security model, and could actually feel intuitive to developers - since access to the full DataSource is still restricted, but view-level access is explicitly granted for the included fields.

      Comment


        #4
        Yes, A and B are reversed in this sample, but our explanation still applies, and the reasons for not supporting viewRequiresRole as an approach for this also still apply.

        Two things may help clarify: imagine that the two DataSources are not SQL DataSources. Then ds_B must literally call the default fetch on ds_A to retrieve the included field. But you have declared that it can't.

        That's the security model. The fact that it happens to be SQL and the equivalent of calling the default fetch is optimized to be a SQL JOIN doesn't change the security model.

        Comment


          #5
          Ok, now I understand the reason for this behaviour, thanks for the explanation.

          Comment

          Working...
          X