-2

I'm trying to learn more about software architecture design patterns, but I'm having some problems with repeating patterns across my application. I will use JS to describe my issue in code ( sorry about that, I will use the least amount of it with the hopes to annoy you the least )

The birds-eye view of the problem goes as follows. UserA is authorized to perform ActionA, but not ActionB, if he attempts to perform that, an authorization error is thrown. There are cases, however, where ActionB needs to happen as a side-effect from ActionA ( which he is allowed to trigger ).

Lets assume that I have an OrderService and a ProductService. In this particular case, the services encapsulate the business logic for the given aggregate root.

A given user is allowed to delete a product, but not to update an order. However, the business rule is, the deletion of a product needs to lock ( or update the order ) the orders that contain that product, the lock essentially disables the order, so that it is not possible to be further edited.

class ProductService {
  delete(user, productId) {
    // Handle authorization
    // Delete a product 
    OrderService.update(user, { locked: true })
  }
}

class OrderService {
  update(user, updates) {
    // Handle authorization
    // Update the order
  }
}

If I pass the same user to the OrderService, an error is expected to be thrown, because he is not authorized to update the order. But that is just a side-effect from deleting a product - he didn't mean to update the order.

How am I supposed to work around this? Should I create a dummy elevated user, which has access to perform all actions, and pass that to the OrderService instead of the real user?

This happens in read situations as well. For example I might have a getAll method on the ProductService which takes in the user and some filters and returns the matching products.

I'd like to have a single source of truth, so I would essentially like to re-use this method as much as possible. However, in a different part of the application, I might want to get the products for another side-effect and the user is not privileged enough to view the products ( I will not end up returning them to the user, but I need them on the server ).

In both of these cases, there was another layer of abstraction to perform the read/update, possibly an Entity framework model.

So, in this case, should I implement a User repository, which has a getAll method, which can be used by other services that would like to read products, but not return them to the user?

That way, I can have a single source of truth for all operations that end up returning the products by using the ProductService.getAll, passing in the current user, and if I'd like to read the products for another side-effect with an unprivileged user ( that I will not end up returning the products to ) I can call the UserRepository.getAll method?

Can services ( or domain models ) use repositories of other aggregates? Like the OrderService uses the UserRepository directly and not through the ProductService?

Edit: I posted this on stackoverflow and got down-voted. When I started looking for a solution, I found similar questions here. If this is also not the correct place for this question, would you point me to a place where I can ask it and receive a good answer? Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.