1

How can I do conditional mapping in Domain Driven Design?

Let's say my application is structured like this:

- Core
  - Domain
  - Application
- Presentation
  - DTOs
  - API

I have an aggregate root called Post which also has a list subscribers to that post.

Here's the deal: Only the moderators are allowed to retrieve this list of subscribers from the Post - not regular members.

One solution would be to have two separate DTOs for the above use cases:

PostDTO that holds information for anonymous users / regular members

RestrictedPostDTO that has additional information only for authorized moderators users.

In this case the API could map the Post to a PostDTO or RestrictedPostDTO depending on the endpoint. The application layer can throw an exception if a non-moderator attempts to call the service method for retrieving post details but in the end the API has to use the correct mapper to prevent leaking information. I see this as a potential design flaw.

I'm wondering how one would perform conditional mapping in the above or similar scenarios.

Is it really just an issue of not having an extra layer of models/mapping between the Domain entities / DTOs? In many scenarios only a subset of an aggregate root is to be returned to the user, so I wonder how to deal with that.

1
  • I am wondering in the above scenario, isn't there just one PostDTO sufficient? It could be filled by the service with the subscriber list when a mod calls the service, and left empty when a regular member calls it. I assume for a regular member, it should be indistinguishable if a Post has no subscribers, or if it has some, but the system does not reveal them.
    – Doc Brown
    Commented Aug 27, 2023 at 17:01

1 Answer 1

3

Q: What information do you return to a user when they perform an action or request data that they are not authorized for?

I believe there are two common answers (resulting in two different designs) so I will flush out both.

#1 - Hide the existence of data, that the user is not authorized to see

If a user tries to access a resource by id that they don't have access to they get a 404. If the user runs a search, the returned list only contains results they are authorized to see (other results are dropped silently).

Given this philosophy, I would argue it is acceptable to return an empty list for the list of subscribers (when the user is not a moderator). That said, it may be useful for the client to have additional information such as knowing the count of how many subscribers there are, or if the client has permission to view the subscriber list. To save extra calls you may choose to add additional attributes (int and boolean respectively) to the DTO.

Hence there is only one DTO (no need to switch between two).

#2 - Confirm the existence of the data and return an "unauthorized" error

Typically this would mean that when a user tries to access a resource by id, there are three possible results:

  • The data is returned (200 OK).
  • The data is confirmed to not exist (404 - Not Found).
  • The data is confirmed to exist, but it is indicated that the user doesn't have permission (403 - Forbidden).

This creates issues for API design when the user is "partially authorized", specifically they can access the post, but not the list of subscribers.

I would force the end user be explicit about the request they are making to the API. For example when making a request for a post they should indicate if they want subscriber data:

  • If the data isn't requested - no problem return a result without it.
  • If the user is authorized - no problem return all the data.
  • If the user is not authorized - return an error **

** - I concede it may be possible to return a partially successful result, but I think that just complicates both the server and client code - I would be tempted to return nothing unless everything succeeded.

The details of how the client requests data is your choice. Have two endpoint (Post and Post+Subscribers) this would allow well defined schemas for each. Alternatively if you use a flag (includeSubscribers) you will have to document how the structure changes based on the flag (possibly flags plural).

In either case your choice of DTO (hence the structure of the returned data) is based on what the client requests - it is deterministic based on the request, not the permissions of the user. In short you're making it easier (predictable) to implement the client.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.