3
I’ve been a software developer for a long time, but I’m always looking to learn "different ways of doing things". I am currently working on a new project and decided to base the architecture on proposals suggested by the community using a combination of DDD, Entity Framework Code First and other "thingies" more. However, in practice and due to some particularities of my business rules, I feel a bit of difficulty in applying some concepts. I would appreciate it if you could help me with these questions.
This is the summary structure of my solution. All projects presented here are Class Library type:
- Core - Contains basic functionalities for the whole system such as resource management, globalisation, etc.
References:
(...) - Domain - Contains the definition of entities and validations.
References:
Core (...) - Repository - Responsible for communication with the entity database and mapping through Fluent API.
References:
Core
Domain
Entity Framework 6
(...) - Security - Applies the functionalities of the above projects to provide security features such as authentications and encryption.
References:
Core
Domain
Repository
Entity Framework 6
(...)
The project Domain contains a class called User defined by the following code (summarised):
namespace Domain.Entities
{
public class User : EntityBase
{
private string _userCode;
private string _userPassword;
//outras variáveis....
private int _customerId;
[MaxLength(255), Required(AllowEmptyStrings = false)] //Estou utilizando Data Annotations para facilitar os testes de integridade e definir restrições básicas ao modelo.
public string UserCode
{
get { return _userCode; }
set
{
ValidateValue(GetType(), nameof(UserCode), value); //O método ValidadeValue está definido na classe base EntityBase e tem o propósito de validar o valor a ser atribuído à propriedade.
_userCode = value;
}
}
[MaxLength(255)]
public string UserPassword
{
get { return _userPassword; }
set
{
ValidateValue(GetType(), nameof(UserPassword), value);
_userPassword = value;
}
}
//outras propriedades...
public int CustomerId
{
get { return _customerId; }
set
{
ValidateValue(GetType(), nameof(CustomerId), value);
_customerId = value;
}
}
//Propriedades de navegação para outras entidades relacionadas
public virtual Customer Customer { get; set; }
public virtual ICollection<Membership> Memberships { get; set; }
//Construtores
public User() { }
public User(string userCode, string userName, string email, Address address = null, bool isAdministrator = false)
{
UserCode = userCode;
UserPassword = "";
//demais inicializações...
CustomerId = 0;
}
//outros métodos...
///<summary>
///Retorna as regras da política de senha vigentes ao usuário por meio de seus papéis.
///</summary>
public PasswordRules GetPasswordRules()
{
var rules = (from r in Memberships.Select(x => x.Role)
where r.RulesPrecedence > 0
orderby r.RulesPrecedence
select r.PasswordRules).FirstOrDefault();
return rules;
}
}
}
I’ll write another class here:
namespace Domain.Entities
{
public class Membership : EntityBase
{
public int UserId { get; set; }
public int RoleId { get; set; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
public Membership() { }
}
}
The questions I need to resolve are:
The class
User
exposes the propertyUserPassword
that, despite having its contents encrypted, I would not want to expose it to the ultimate developers, so that it was an internal property. However, how to do this if in the project Repository I need access to this property in order to map it to its column in the database table?As you can see, the class
User
has a navigation property for the entityMembership
, in a one-to-many relationship. AMembership
, in turn, has two navigation properties (one forUser
and another toRole
), so thatMembership
makes a many-to-many relationship betweenUser
andRole
. Through these relationships and properties, a user can know their password policy rules (defined in Role), as shown in the methodUser.GetPasswordRules()
. So far, so good. The problem is that, a certain user will not necessarily be able to access the registration of papers (Roles), in the same way that someone who has access to the registration of papers will not necessarily have for the users. Therefore,Membership
should not expose its browsing properties. But if I withdraw the browsing propertiesUser
andRole
ofMembership
, how can I supply the functionality of the methodUser.GetPasswordRules()
since the project Domain does not access database?
There are some other issues, but I think these two are the main ones. I hope I’ve been clear. Thanks for any help.
Look at that answer: http://answall.com/a/80696/61561
– Renan Carlos
Good afternoon, have you thought about using ASP.NET Identity to take care of the authentication and authorization part in the application?
– Felipe Deguchi
@Renancarlos, this is really a good discussion (use or not Repository Patterns on EF). However, I did not see how the answers of this post would help me. Unifying the Domain layer with Repository is not a possibility.
– Eric Cordeiro
@Felipedeguchi, The Security layer performs authentication and authorization based on an existing business model and can be used on any platform (Windows, ASP.NET MVC, Webapi, Console, etc.) is not limited to the web infrastructure.
– Eric Cordeiro
I don’t think it would be possible to leave the database connection layer in a Webapi and use DTO’s (Data Transfer Object) for when it is necessary to access data from
User
, so developers would only have access to the data you want them to have. The same goes for the second question, within a DTO you would have the Password rules without exposing the Membership.– Felipe Deguchi