I perform model validation in my controllers, but a second business validation needs to take place at the service/business level. This is usually related to user permission: does the current user have access to the customer/order info he is trying to get or post?
My first (and working) approach is to pass either the entire User
instance or its Id
(by calling User.Identity.GetUserId()
), which would be enough most -if not all- of the time. So I'll have something like this:
public IHttpActionResult Get(int id)
{
try
{
var customer = customerService.GetById(id, userId);
return Ok(customer);
}
catch (BusinessLogicException e)
{
return CreateErrorResponse(e);
}
}
But I don't really like the fact that with this approach I'm going to have to include an extra parameter in pretty much every call to my service layer. If I am calling a GetById()
method, I want to get something by providing an ID, not an ID and a user ID.
A simple workaround would be something along these lines, which also works:
public IHttpActionResult Get(int id)
{
customerService.SetCurrentUser(User.Identity.GetUserId());
try
{
var customer = customerService.GetById(id);
return Ok(customer);
}
catch (BusinessLogicException e)
{
return CreateErrorResponse(e);
}
}
But instead of having to make a separate call to set the current user, I'd like this to be done automatically with every call to the service. How can I do it?
Here's what my service looks like:
public class CustomerService : EntityService<Customer>, ICustomerService
{
public string UserId;
IContext context;
public CustomerService(IContext context) : base(context)
{
this.context = context;
this.dbSet = context.Set<Customer>();
}
public void SetCurrentUser(string userId)
{
UserId = userId;
}
public DTO.Customer GetById(int id)
{
if (!IsAccessibleByUser(id))
{
throw new BusinessLogicException(ErrorCode.UserError, "UserId: " + UserId);
}
return dbSet.FirstOrDefault(x => x.Id == id).ToDto<Customer, DTO.Customer>();
}
public bool IsAccessibleByUser(int id)
{
return context.UsersAPI.Any(a => a.AspNetUsersID == UserId);
}
}