Recently someone asked questions about the IDDD sample code and authorization. Basically the question was, why can’t I authorize the user in the model to start a new Forum Discussion? The developer would pass in a “session” object to the Forum startDiscussion() and have the Forum double dispatch to the “session” to check for authorization:
public class Forum ... {
...
public Discussion startDiscussion(Session aSession, String anAuthorId, ...) {
aSession.assertAuthorizedDiscussionAuthor(this.tenant(), anAuthorId);
...
}
...
}
Take a look at IDDD pages 75-79, and specifically at the refactored code on pages 78-79. It’s not that it is absolutely wrong to in essence authorize the user in the model. Rather, it’s that the authorization is done for free when obtaining the necessary Author instance by way of the CollaboratorService.
Further, it’s a matter that the Author is an essential part of the Ubiquitous Language, while the “session” is not. If anything, rather than pass in a “session” object (or worse yet, SecuritySession), pass in CollaboratorService instead, and double dispatch on the CollaboratorService to get the Author from the Forum’s own Tenant and parameter String anAuthorId:
public class Forum ... {
...
public Discussion startDiscussion(
CollaboratorService aCollaboratorService,
String anAuthorId,
...) {
Author author = aCollaboratorService.authorFrom(this.tenant(), anAuthorId);
if (author == null) {
throw new IllegalArgumentException("Not a valid author.");
}
...
}
...
}
In my sample code I show the Forum Application Service obtaining the Author via CollaboratorService. This is not wrong because normally the API would serve as the natural client of the model. When using the Hexagonal (Ports and Adapters) architecture, requests from disparate user agent types would all be adapted to use a single API call. This is based on use case, not on user agent type. But you could pass in CollaboratorService to the Forum if you prefer.