As already pointed out, Niclas was talking about code security and not AAA security, but this is important too:

Aye wrote:
The one thing I've noticed in other frameworks is that they treat
security outside of a domain context. Static security models at
service level and/or domain object levels are good but I think it
paints only a part of the picture. For example, imagine a case where
the user is allowed to issue a command/invoke a service; but the
constraints are that he/she can do this from 9 AM to 5 PM. This
doesn't even take into consideration what state the domain object in
question is in (e.g. 'Active' status).  In my mind the domain context
in which the request is made is very important and that having a
role(or permissions) is just a starting point. I've seen a lot of IF
statements where the permission is checked AND then a dozen more
conditions that are domain specific is checked. In my mind they're all
together and is a part of the security model.

Completely agree!

Ok, next. Let's say that the user got the authorization to issue the
command successfully; the domain object (or objects) returned should
also have authorization metadata associated with its properties so
that the GUI (or another client) is able to figure out what can be
changed and what can't be. I actually think qi4j might already be
handling this with the Property interface (@Immutable also).

Agree. The way I'm doing this in StreamFlow is like this: the domain model is only running on the server, and is exposed through domain-oriented REST endpoints (implemented using Restlet). Each object will have authorization checks for general access, and then each operation will be a subresource of its own, which can be GET or HEAD in order to check availability. If it returns 200 then a) the operation is valid from a domain state point of view and b) the user actually has authorization to perform it. If not a) then 404, and if not b) then 401. In both cases the UI can detect this and change the UI for it.

Example:
inbox/task/{id}/complete
=> GET gives form for completing the task
=> HEAD checks availability and security
=> POST performs the command

Actual implementation on the server would be:
Task.complete(CompleteTaskCommand)

where CompleteTaskCommand is a ValueComposite so it is easy to generically create a form or post as JSON.

Doing GET on /inbox/task?{task query} will retrieve a listing which contains the specific details needed to show an overview of the inbox. That operation is:
Inbox.task(TasksQuery)
where TasksQuery is a ValueComposite.

This achieves both RESTfulness, domainlevel RBAC, CommandQuery separation (complete is command, task is query), and other goodness.

/Rickard


_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to