Restricting access via facets with masked elements
Watching the inaugural episode of The Art & Science of CAP, in particular around 39 mins in, Daniel was showing an example of a projection where some of the details of the entity -- upon which the projection was being made -- were deliberately restricted.
Here's the example:
@readonly entity Books as projection on my.Books { *,
author.name as author
} excluding { createdBy, modifiedBy };
In terminology terms, the
Books
entity being defined here is called a facet.
There are three details that qualify the projection.
Taking the last one first i.e. the excluding { ... }
clause, this is straightforward and explicitly excludes two elements from the facet. Perhaps the interesting thing here is the fact that these elements come from the managed
aspect which has been mixed in to the Books
entity definition (entity Books : managed { ... }
).
Then there's the *
inside the signature1 which does what we expect it to do - include all the elements from the projectee My.Books
. Perhaps the interesting thing here is that this on its own ({ * }
) would be unnecessary (i.e. implicit in just ... as projection on my.Books;
) except for the fact that we want to modify that list of elements, using the last detail.
The last detail is author.name as author
, requiring the { * }
part to ensure the rest of the elements are included alongside this one. Definitely the most interesting thing here is that this is a really neat way of restricting access to the author details via the association that the author
element is defined as in the entity. By "clobbering", or simply "masking" that author
association with a new definition (author.name
) which points to the name
element from the target of the association (the Authors
entity), the job is done in one simple redefinition.
This is lovely, and even simpler than the example in the Exposed Entities part of the section on CDL in Capire:
service CatalogService {
entity Product as projection on data.Products {
*, created.at as since
} excluding { created };
}
In this Products
projection example, the created
element is explicitly excluded, rather than being "clobbered", and a new element since
is declared instead, referencing created.at
. In case you're wondering, created
is an element from the ManagedObject
aspect shown earlier in the CDL section:
aspect ManagedObject {
created { at: Timestamp; _by: User };
}
So in contrast to the author
example, this is the masking of details from a structured type. And even here there's something of interest - this structured type is an anonymous inline one, and is the equivalent of:
type Created {
at : Timestamp;
_by : User;
}
aspect ManagedObject {
created : Created;
}
So there you have it. Always something interesting to observe!
Footnotes
- I think that's the right term for the
{ ... }
following a projection declaration - let me know if you think it's called something else.