Understanding srp principle in solid with nlayers - c#

I have a web application with the following layers:
View
Business
Entities
Repository
I want to send an email to a User when he or she is registered.
I have the class User, in the Entities layer, and the classes UserBussines and MailBusiness in the Business layer.
The problem is that I don't know where is correct to send the email to the user.
I see some options
1) In the controller:
UserBusiness.AddUser();
MailBusiness.SendEmail();
2) In the business
UserBusiness.AddUserAndSendEmail()
{
AddUser();
MailBusiness.SendEmail();
}
In the two options I think that I'm not fulfilling the SRP in the SOLID principle, because I'm giving two responsibilities in one method.
I'm not understanding the principle? Or am I doing something wrong?

You have user registration scenario:
Given not registered user
When user registers
Then user becomes registered
And greeting mail is sent
This scenario should exist in your business logic layer, because:
It is scenario of your business domain
It should exist whether you use web application, desktop application, or mobile application.
So, you should have some application service (e.g. UserService) which will act as coordinator for user repository and email service:
public void RegisterUser(User user)
{
// possibly you should also check that user is not registered yet
_userRepository.Add(user);
_emailService.SendGreeting(user);
}

Related

Can domain event be raised in domain service?

I'm wondering if domain event can be raised in domain service? I've got such a code written in C#. Of course it works, but is it correct from DDD point of view?
First example is related to user deletion. In my system Account has multiple users. After user removal AccountUserRemovedDomainEvent is raised. Then subscriber in infrastructure layer handles audit log management. It adds proper log describing this action.
public void RemoveUser(AccountUserEntity user, AccountEntity account)
{
AccountUserRepository.Delete(user);
DomainEvents.Raise(new AccountUserRemovedDomainEvent(user));
}
That's the second example. In that case except creating audit log subscriber in infrastructure layer is sending mail with activation link to the user.
public void SaveAccountUser(AccountUserBasicInformation information, AccountEntity account)
{
var user = Mapper.Map<AccountUserEntity>(information);
account.Users.Add(user);
user.Account = account;
DomainEvents.Raise(new AccountUserAddedDomainEvent(user));
}
A domain event would typically be the result of an action/command being applied to a domain object. As such it probably wouldn't be something that a domain service is concerned with. You may need to have some technical system events/messages but those are a bit different and wouldn't be in domain services.
I like to have a method return the domain event(s) which facilitates testing, instead of a singleton that raises the events. If you end up with a domain service that interacts with multiple domain objects you may opt for returning the events but chances are, when using event sourcing anyway, that you'd need to the event streams that the events have to be added. Depending on your implementation the aggregate can keep track of new events also. In both scenarios you have a container for the event(s) so no need to return/raise them anyway.

Authorization in a layered application

I am working on a pretty simple project that is mostly made up of getters and searches and access to certain data is limited depending on the user. I want to use this opportunity to do some best practices when it comes to security, authorization in this case.
The application is activated once at which time a token is generated and used for future requests.
My application has a web api for the endpoint which sits on top of a set of services which sits on top a set of repo's which sits on top of a sql server db. All the controllers do is forward the request down to the service layer.
Here is an example controller:
[ApiAuthorize]
[RoutePrefix("api/Catalogue")]
public class CatalogueController : ApiController
{
private ICatalogueService _catalogueService;
public CatalogueController(ICatalogueService catalogueService)
{
_catalogueService = catalogueService;
}
[HttpGet]
[Route("GetCatalogues")]
public IHttpActionResult GetCatalogues(string branchEan)
{
var catalogues = _catalogueService.GetCatalogues(new GetCataloguesRequest()
{
BranchEan = branchEan
});
return Ok(catalogues);
}
}
My custom authorization attribute checks the token and if valid pulls the user details out from the token and creates a generic principle which is then available in my controllers.
To me the web api is just a way to expose my business\service layer and authorization should be done lower down in my service layer but I can't think of a clean way to get that information down to that layer. In the above example, the service layer will need to check if the user (from the token) has access to that particular branch which means the service layer will need to know who is making the request. The two solutions I can think of is:
1) I am using a request\response pattern for my service layer so I could create an abstract base class called 'Request' as an example which could store all the user details and each request object to the service layer could inherit from this therefore providing user details to my service layer.
public abstract class Request
{
public Request(string username)
{
this.Username = username;
}
public string Username { get; private set; }
}
public class GetCataloguesRequest : Request
{
public GetCataloguesRequest(string username) : base(username)
{
}
}
2) To define an interface, for example ISecurity, which is then injected into my service layer but this would require the layers above my service layer to implement the interface.
I read here - Placing authorization into the service layer rather than Web API layer
- to create an authorization layer but I am not sure of the technical implementation of this.
Any ideas?
What you are looking for is fine-grained, externalized authorization:
fine-grained: you want to create authorization policies that take into account multiple parameters or attributes and possibly relationships between the client (the requestor) and the targeted entity e.g. a listing in your case.
externalized: you want to decouple the business logic from the authorization logic. In your question you complain about how complex the code and the SQL statements are becoming. This is a direct consequence of not clearly separating business logic from authorization logic.
There is a model called attribute-based access control (ABAC) that defines an approach to fine-grained externalized authorization. NIST, the National Institute of Standards and Technology, has produced a report on ABAC which you can read online.
OASIS, the organization for the advancement of structured information standards, has defined a standard called XACML (eXtensible Access Control Markup Language) to implement ABAC.
XACML brings you:
an architecture as illustrated below
The policy enforcement point (PEP) intercepts your API calls. It protects your API, inspects the messages and sends an authorization request to the policy decision point (PDP).
The policy decision point (PDP) evaluates incoming authorization requests from the PEP against a set of authorization policies written in XACML. The PDP eventually reaches a Permit or Deny decision. To reach decisions it may need to look up additional attribute values from databases, web services, LDAP, or files. These are called policy information points in the architecture.
a policy language: the XACML policy language is attribute-based which means it uses attributes to define what can be allowed and what is not. For instance, you could define rules such as:
a real estate agent can see all the listings if and only if the listing location == the agent location
a real estate agent can edit a listing if and only if he/she owns the listing
a real estate agent can close a listing if and only if the listing's item is sold and if and only if the agent is the person that sold the item.
a request/response scheme: XACML also defines a way to query the PDP and to get responses back. A PDP can be queried either via single questions or via multiple questions in a single request e.g.:
Can Alice view listing 123? Yes, permit.
Can Alice view, edit, or delete listing 123? Permit; Deny; Deny.
With a XACML-based approach, you get to maintain your business logic and your API separate from the authorization logic. This has several benefits:
you can always reimplement the API and keep the same authorization model
you can easily expand your API without having to rewrite the authorization
you can change your authorization logic independently of your code
you can audit your authorization logic more easily
your authorization logic is technology-neutral. It works for REST APIs, web services, databases, and more
I recommend you check out the following resources:
the OASIS XACML website
the ALFA plugin for Eclipse - a free tool to write XACML policies.
The XACML developer community
There are both vendor and open-source implementations of XACML:
Axiomatics is a vendor solution that provides both .NET and Java XACML implementations
SunXACML is a long-standing open source Java XACML implementation
HTH,
David.

ASP.NET MVC: seperatation of concern for normal/admin user

I'm going to separate admin and normal user section of my ASP.NET MVC 5.2 project. My admin area and normal user area have much things shared, however privileges and details for each of them is different.
Right now I don't know how to separate admin area and normal user area. I don't know if I should create different project for admin-panel or I just should route admin to different path and use the same controllers? Or should I route to different path and use different views/controllers?
And a side question, is it possible to have real physically separated admin and normal user area in the same ASP.Net MVC solution or not?
Usually in applications there are various endpoints using the same business logic. What should we do in this scenario? We can easily copy one endpoint and paste it in another, but once the business case is changed, we'd need to change everywhere in our code.
In favor of separation of concerns, controllers should have "code" logic and another layer should have the "business" logic. E.g. Controllers might define how properties are named, but not how long an username is. An username should be long at least 3 chars no matter which controllers tries to register the user.
All of that operation with entity models to meet the business case requirements should be moved to a separate layer. Usually called Service layer.
That all of your controllers can use any of that services without being aware from the business scenario behind.
A simple example here are two controller actions - one of the - editing your own profile and the other - the administrator editing an arbitrary user profile.
[Authorize]
public IActionResult Edit(UserViewModel model) {
if(model.Id != this.CurrentlyLoggedUser.Id) {
return this.RedirectToAction(...);
}
var userService = new UserService(); // inject maybe
userService.EditById(model.Id, model);
return this.View();
}
and the admin action
[Authorize("Admin")]
public IActionResult Edit(UserViewModel model) {
var userService = new UserService(); // inject maybe
userService.EditById(model.Id, model);
return this.View();
}
The "code" logic here is - create service, invoke the encapsulated edit logic. Also some security reasons the action should take care about - Authorize and Authorize Admin.

Beginner here: How does my Repository Layer know which user is logged in?

I know this is a super novice question, but I'm having a tough time understanding this. I'm implementing WebSecurity in my n-tier application. I've placed all WebSecurity code in my repository layer (closest to the db layer).
I have code like this:
public bool LogIn(string userName, string password, bool rememberMe)
{
return WebSecurity.Login(userName, password, rememberMe);
}
public void LogOut()
{
WebSecurity.Logout();
}
WebSecurity doesn't need to know the context for logging in - I pass the parameters. But what about logging out? With 10 users logging out, how does this code right here know which user to log out? Does the context of the user somehow get pushed all the way down to the repository layer, from the browser client to my API controller, through my services layer?
I would create service class to implement this functionality. This service layer method should have IPrincipal and IUserRepository injected. IPrincipal interface stores information about current user. HttpContext.Current.User implements it.
public interface IAuthenticationService
{
bool SignIn(string userName, string password, bool rememberMe);
void SignOut();
}
public class WebSecurityAuthenticationService : IAuthenticationService
{
public WebSecurityAuthenticationService(IPrincipal user, IUserRepository userRepository)
{
}
....implementation...
}
You should use IOC container to define binding between IPrincial and HttpContext.Current.User and between IUserRepository and its database based implementation. I recommend Ninject, but choice is yours.
Your repository layer shouldn't know which user is logged in. Your repository layer shouldn't even know that there is a user. All of your authentication should be handled by your web application - your web application then, having authenticated the user, accesses your repository layer, which simply does whatever it's told to do and doesn't concern itself with authentication.
Update: As John Saunders points out, this would not tie your web application to the membership database/tables but to the membership system you are using. If even this is too tightly-coupled for you, you could think about defining an IMembershipService interface, which you pass into your controllers' constructors (potentially via dependency injection). You would then create a concrete implementation of IMembershipService that implements Login and Logout via WebSecurity.
This way, if you decide you want to implement membership in a completely different way, your only restriction is that your replacement membership service must implement IMembershipService - you can change the technology and data structures entirely and your web application is none the wiser.

Retrieving the currently authenticated user in a WCF service

Today, I implemented a custom authentication provider for my WCF service. It is able to determine if my user is valid or not, just as expected.
So, now I have this class:
public class MyCustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
User apiUser = User.Login(userName, password);
// other logic goes here.
}
}
The behaviour of my application depends on what objects the User can access. So, how can I get my User object from here to my service class? There is no immediately obvious way that I can see, as my service class does not inherit from anything by default, unlike the ASP.NET controllers.
My first instinct is to set up a static parameter in MyCustomValidator and then read it from there, but I suspect that a race condition could occur. Can anyone confirm or deny my suspicions?
And most importantly: Is there a better way to do this? This is the first time I have ever used WCF, so I'm not aware of the best practices involved here.
Thank you for your time.
You want to pass some data from validator to service instance. It is bad because you can't do it. UserNamePasswordValidator is only for validating credentials (user name and password). You don't have access to anything from your validator. It even doesn't see current operation context because it runs in different thread. Using static parameter is not a sloution - as you mentioned it is race condition.
I think you need to implement custom authentication and authorization and it is not easy:
WCF Authorizaton, Custom Authorization, Custom credentials and validation

Categories