Search code examples
c#asp.net-coreonion-architecture

Login process within Onion Architecture


I want to implement a login process within the Onion Architecture. I can't get my head around how to go about it correctly. Below is my Repository class that will talk to the database. How would I go about checking that an email had not already been entered into the table. It seems the only parameters I can pass in are Model objects or entities from my BaseClass. My Base class contains only a string for Id.

    public class RentalsRepository<T> : IRentalsRepository<T> where T : BaseClass
{
    private readonly RentalsDBContext _Context;
    private DbSet<T> entities;
    string errorMessage = string.Empty;

    public RentalsRepository(RentalsDBContext _Context)
    {
        this._Context = _Context;
        entities = _Context.Set<T>();
    }

    public T Get(string Id)
    {
        return entities.SingleOrDefault(e => e.Id == Id);
    }

Currently all I can think of is returning all the user entries and then searching the list but I imagine this is not very efficient. Thanks!


Solution

  • Basically you first of all would extend your Repository with the mentioned GetByPredicatemethod that is basically only a Wrapper for SingleOrDefaultor FirstOrDefault (or other LINQ methods that take a lambda expression / predicate). Your repo will then look similar to this:

    public class RentalsRepository<T> : IRentalsRepository<T> where T : BaseClass
    {
       private readonly RentalsDBContext _Context;
       private DbSet<T> entities;
       string errorMessage = string.Empty;
    
       public RentalsRepository(RentalsDBContext _Context)
       {
          this._Context = _Context;
          entities = _Context.Set<T>();
       }
    
       public T Get(string Id)
       {
          return entities.SingleOrDefault(e => e.Id == Id);
       }
    
       public T GetByPredicate(Func<T, bool> predicate)
       {
          return entities.FirstOrDefault(predicate);
       }
    }
    

    In your Businesslogic you would then call this method like so:

    public void PerformLogin(string username, string hashedPassword)
    {
        var user = _repository.GetByPredicate(x => x.Username == username);
        if(user != null)
        {
           if(user.HashedPassword == hashedPassword)
           {
              // Login succeeded do all you need to set usersession here
              return;
           }
        }
        // If we´ve come this far either there is no user or password was incorrect. We need to inform the user that login hasn´t succeeded
       throw new LoginFailedException("Login failed. Username does not exist or password is incorrect.);
    }
    

    Basically as you can call this GetByPredicateanyway you want. Please consider that each call to GetByPredicatwill result in a SQL expression so do not use to complex conditions. Only use simple conditions like the one I´ve been showing above.