First and foremost: making a ticket for us to add some snippets like this in the LKB. You’re right that they are missing.
So, if you’re using a generated data-service, somewhere in your Application class, an IDataService will be built, and that’s where you inject your custom IDataObjectAuthorizationPolicy. I’m pasting below an example below that makes LEAF’s DataObjectAuthorizationPolicyQueryBased and imports the relevant metadata for LEAF’s authorization policies. Note that this includes all the BeanMetadata for every permission type, not just the query-based permission. But we will only honor permissions for policies you’re actually using. You can combine multiple policies to use multiple permissions using DataObjectAuthorizationPolicy, which is a composite policy.
IEventService eventService = EventServiceLocal.newBuilder()
.build();
eventService.start();
// This AtomicReference approach lets us use the same services we're potentially protecting to store authz DataObjects and queries
AtomicReference<IDataObjectService> dataObjectServiceRef = new AtomicReference<>();
AtomicReference<IDataObjectQueryService> queryServiceRef = new AtomicReference<>();
AtomicReference<IDataObjectQueryEvaluationService> queryEvalServiceRef = new AtomicReference<>();
IDataObjectAuthorizationPolicy authorizationPolicy = DataObjectAuthorizationPolicyQueryBased
.newBuilder(dataObjectServiceRef, queryServiceRef, queryEvalServiceRef)
.build();
IDataService dataService = DataServiceTransient.newBuilder(eventService)
.withDataObjectAuthorizationPolicy(authorizationPolicy)
.build();
dataObjectServiceRef.set(dataService.getDataObjectService());
queryServiceRef.set(dataService.getDataObjectQueryService());
queryEvalServiceRef.set(dataService.getDataObjectQueryEvaluationService());
dataService.upsertResources(CoreResourceDescriptors.AUTHORIZATION, Context.makeSystemContext());
If you’re on a version pre-3.3.0, use AuthorizationResourceLocations.INSTANCE instead of the CoreResourceDescriptors.AUTHORIZATION value.
From there you can start adding Role DataObjects, putting DataObjectQueryPermission DataObjects as children under the Role DataObjects (ie DataObjectTrees as the role-permission relationship is parent-child). Then once you have your Role DataObjects, you can start making SecurityGroup DataObjects, which reference one or more Role DataObject IDs in a SetOfStringsField. You can add these DataObjects however you want: from Java code, storing in a file and parsing and adding, from a UI like LEAF’s Admin App, or whatever.
The only tricky thing with DataObjectQueryPermissions is you need to first persist the DataObjectQuery in the DataObjectQueryService you provide when constructing the authz policy, bc what you place on the DataObjectQueryPermission is the ID of the persisted DataObjectQuery.
So here’s an example of making a DataObjectQuery, persisting it, making the Role, DataObjectQueryPermission, and SecurityGroup DataObjects, persisting those, and then making a User that has the permissions given by that SecurityGroup.
DataObjectQuery query = dataObjectQuery(types("ProtectedResource"), stringEquals("classification", "U"));
query = getOnlyElement(dataService.getDataObjectQueryService()
.upsert(List.of(query), Context.makeSystemContext()));
IDataObjectService dataObjectService = dataService.getDataObjectService();
DataObject role = DataObject.newBuilder()
.withType(RoleMetadataConstants.TYPE)
.with(RoleMetadataConstants.NAME, "Unclassified-View-Role")
.build();
role = getOnlyElement(dataObjectService.addRoots(List.of(role), Context.makeSystemContext()));
DataObject dataObjectQueryPermission = DataObject.newBuilder()
.withType(DataObjectQueryPermissionMetadataConstants.TYPE)
.with(DataObjectQueryPermissionMetadataConstants.DATA_OBJECT_QUERY_ID, query.getId())
.with(DataObjectQueryPermissionMetadataConstants.CAN_ADD, false)
.with(DataObjectQueryPermissionMetadataConstants.CAN_READ, true)
.with(DataObjectQueryPermissionMetadataConstants.CAN_UPDATE, false)
.with(DataObjectQueryPermissionMetadataConstants.CAN_DELETE, false)
.build();
dataObjectService.addChildren(List.of(dataObjectQueryPermission), role.getId(), Context.makeSystemContext());
DataObject group = DataObject.newBuilder()
.withType(SecurityGroupMetadataConstants.TYPE)
.with(SecurityGroupMetadataConstants.NAME, "Unclassified-View-Group")
.with(SecurityGroupMetadataConstants.ROLE_IDS, Set.of(role.getId()))
.build();
group = getOnlyElement(dataObjectService.addRoots(List.of(group), Context.makeSystemContext()));
User user = User.newBuilder()
.withUsername("blake.doe")
.withAuthorizationProp(Sets.newHashSet(group.getId()))
.build();