Adrian,
I must be missing something. Still using the Example component as an
example: the service definition called a service permission, which
called a script, which ultimately called Security.hasPermission.
Your modification has the service definition use the <required-
permissions> which ultimately calls authz.hasPermission(). So, both
methods end up calling a single hasPermission() method. What changed?
The only difference I see is that the permission string moved from a
script to the service definition. Is that the desired benefit?
It is indeed the designed benefit. Previously, we had this:
1. A service with a permission service attached. The permission
service checked static permission, and possibly (not in the case of
the example component, but honestly this component doesn't utilize the
full potential of the new code) processed other logic which would
determine of the user had the ability to perform that function.
2. A screen definition which checked permissions, okay again the
example component doesn't utilize all the possibilities, but let's say
we wanted to add a delete button to the screen to delete the example.
Using the old method you would then call the has-permission screen
operator and check for a static permission probably something like
EXAMPLE_DELETE.
Now, let's say we want to allow anyone to create examples, only the
person who created the example and any admin can update or delete it.
Using what we had in the old model, the permission service logic would
need to be adjusted to grant permission to the owner of the example.
However, the screen operator will still only pickup the static
EXAMPLE_DELETE permission. We don't want to give everyone delete
access, we only want them to delete the examples they created. So,
only admins or users with EXAMPLE_DELETE would see the button.
The new authz implementation handles all of this for us. First we
define the permissions, access:example, update:example and
delete:example as seed data. These are also attached to the example
admin user's security group.
We will give all users access:example permission so they can access
the application, but only give admins the update and delete permissions.
Next we define the Dynamic Access logic. Very little code need, check
the example from the exampleId which is passed in the
permissionContext and part of the permission string (which we will
define in a moment) and if the owner is the userId return true,
otherwise return false. This can be groovy or a simple method if
desired. We then register this logic with the permissions in the seed
data file. The same logic can be attached to both update:example as
well as delete:example.
Now we will configure the services to include permissions. The
createExample will have no permission or set it to access:example to
make sure only users who can access the app can create (I have other
more complex ideas for this, but this is a simple example). The
updateExample service should be set with "update:example:${exampleId}"
as the permission, the deleteExample service set with "delete:example:$
{exampleId}" permission.
Finally, we configure the screen definition and add the delete button
(or update button whatever the case may be). But we do a permission
check here as well for "delete:example:${exampleId}" (note: exampleId
should be in the screen's context) to restrict the display of the
button.
Now, using the new API the button is displayed under two conditions:
1. the user is an admin and has delete:example permission
2. the user is the owner of the example
The exact same logic is used by the service engine when submitting the
request, so you can be sure that if the button was displayed then
permission will be granted when submitting the form.
Maybe later you want to change how this works. Maybe being the owner
is not enough, you must the be owner and have been active in the last
5 days. So, you simply edit the logic in the groovy (or simple method)
script and clear the cache. The new logic kicks in, effective in all
places which check that permission.
This is what I mean by 'centralized'. Instead of having security split
up between the Security API and the Service Engine Permission API,
everything is moved and centered around the permission.
Andrew