Different DTOs based on roles/permissions

Hi!

I have an application scenario where I need to return different DTOs depending on the user permissions.

Can I find anything about this in the documentation or can you point me in the right direction?

Kind regards
Carsten Vogelsang
Germany

This is generally not a good idea since it goes against having an explicit API contract for a specific API. Another approach would be to have the single response with nullable/optional properties that only populate on specific scenarios along with common properties for both.

When defining your API DTOs, you’ll see the use of IReturn<T> where T is the response DTO. If you need to have completely different data structures returned, you could have your response type encapsulate both. For example

public class MyRequest : IReturn<MyResponse>
{

}

public class MyResponse
{
    public AuthUserObj AuthUserData { get;set; }
    public AnonUserObj AnonUserData { get;set; }
}

public class AuthUserObj
{
...
}

public class AnonUserObj
{
...
}

This is not ideal still since the client will then have to change property based on being authenticated or not.

You can still return different objects as a response in your service like any other object, but again, this breaks explicit data contracts set by your API. Eg,

public object Get(MyRequest request)
{
...
    if(session.IsAuthenticated())
        return new AuthUserObj
        {
           ...
        };

    return new AnonUserObj
    {
        ...
    };
}

Hope that helps.

1 Like

Hello Darren!

Thank you for your quick support. :+1: I am still a bit unsure how to realize our particular scenario with your explanations. Sorry, I also expressed myself unclearly/badly in my question. I’ll try to explain the scenario better again:

The API is used by members of 3 different purchasing associations of a certain industry. Depending on the membership, the member receives different quality of product master data, so depending on the purchasing association membership. As an example, members of association A receive only 1 image about a product and only basic information, members of association B receive all available images about a product and all properties.

Also, a member may be blocked for data of some exclusive suppliers (manufacturers) because this member is not a customer of this supplier.

So you are right in pointing out that it would be more correct to have only one API contract. But I need to be able to filter the data (properties) before response based on the role of the user and rights of the user.

Role: Member (API user) has membership in purchasing group A
Permissions: Member has no access to data of supplier X, supplier Y, …

Product 1 has 2 images - 1 of which is of the main image type - and comes from supplier N.
Product 2 is from supplier X.

The member receives this response object back from the API:

Product 1 with 1 image (main image) and some product properties that are empty because the member only receives basic data due to the membership…

Product 2 is not returned at all because the member does not have the right to access data from supplier X.

Conclusion:
I am not yet clear at which point and how to realize the data filters (data from SQL Server database). According to your objection, I would only return the same DTO (for all roles and permissions), but with partially empty values. But how do I do it correctly in ServiceStack? In a normal .NET Core web API I would now have different database queries based on authentication (and role, permissions).

Sorry, but my experience with ServiceStack is still in the early stages. I watched some ServiceStack Youtube videos this week and reprogrammed a demo and bought the license today because the architecture and efficiency is very impressive.

Greetings
Carsten
Germany

You can do it one, but I wouldn’t mix secure & public services and would recommend maintaining different APIs for public and secured APIs which require authentication which clients call whether they’re authenticated or not.

The structure of the DTOs returned is up to you, i.e. whatever structure best captures the client needs.
From what I understand of your requirements all your business logic needs is what Roles and Permissions the authenticated users have, which you can access with:

ServiceModel’s (DTOs)

[ValidateIsAuthenticated]
public class MyProducts : IReturn<ProductsResponse> {}
public class PublicProducts : IReturn<ProductsResponse> {}

public class ProductsResponse
{
    public List<Product> Results { get; set; }
    public ResponseStatus ResponseStatus { get; set; }
}

Services

public class MyServices : Service
{
    public MyDep MyDep { get; set; }

    public object Any(MyProducts request)
    {
        var session = SessionAs<AuthUserSession>();
        var roles = session.GetPermissions(AuthRepository);
        var permissions = session.GetPermissions(AuthRepository);
        
        return new ProductsResponse {
            Results = MyDep.GetProducts(roles, permissions) 
        };
    }

    public object Any(PublicProducts request) => 
        new ProductsResponse { Results = MyDep.GetPublicProducts() };
}

Both Services can return the same Response DTO if it makes handling on the client easier, and since the output of APIs is deterministic by its input the public anon requests could even be cached.