OrmLite Auth Repository Multi Tenancy and Required Permission attribute closing db connection

Hi,

I am using the new OrmLiteAuthRespositoryMultiTenancy so it uses the AppHost.GetDbConnection() method so the db can bet set on each request. When I’m using the RequiredPermissionAttribute, it works fine if the user has the permission, but if they don’t have the required permission I get the following:

ExecuteReader requires an open and available Connection. The connection’s current state is closed.

Stack trace below:

Re the “RoleBasedAuthRepository”, this is my custom AuthRepository which derives from OrmLiteAuthRepositoryMultitenancy. It is failing while calling base.GetUserAuth(userAuthId).

ServiceStack.Auth.OrmLiteAuthRepositoryBase`2.<>c__DisplayClass21_0.<GetUserAuth>b__0(IDbConnection db) at ServiceStack.Auth.OrmLiteAuthRepositoryMultitenancy`2.Exec[T](Func`2 fn) at ServiceStack.Auth.OrmLiteAuthRepositoryBase`2.GetUserAuth(String userAuthId) at RoleBasedAuthRepository.HasPermission(String userAuthId, String permission) in RoleBasedUserAuthRepository.cs:line 51 at ServiceStack.AuthUserSession.HasPermission(String permission, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.<>c__DisplayClass8_0.<HasAllPermissions>b__0(String x) at System.Linq.Enumerable.All[TSource](IEnumerable`1 source, Func`2 predicate) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IRequest req, IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.Execute(IRequest req, IResponse res, Object requestDto) at ServiceStack.RequestFilterAttribute.RequestFilter(IRequest req, IResponse res, Object requestDto) at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)

Not sure what the request is but we don’t stand a chance to be able to reproduce this without access to the missing classes in the StackTrace that’s causing the exception.

Hi,

I have re-plumbed to purely use OrmLiteAuthRepositoryMultTenancy natively (rather than my own derivative), and below is the stack trace of the error.

System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection’s current state is closed.
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() at ServiceStack.OrmLite.OrmLiteCommand.ExecuteReader() at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.ExecReader(IDbCommand dbCmd, String sql) at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ConvertTo[T](IDbCommand dbCmd, String sql) at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.SingleById[T](IDbCommand dbCmd, Object value) at ServiceStack.OrmLite.OrmLiteReadApi.<>c__DisplayClass19_01.b__0(IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func2 filter) at ServiceStack.OrmLite.OrmLiteReadExpressionsApi.Exec[T](IDbConnection dbConn, Func2 filter)
at ServiceStack.OrmLite.OrmLiteReadApi.SingleById[T](IDbConnection dbConn, Object idValue)
at ServiceStack.Auth.OrmLiteAuthRepositoryBase2.<>c__DisplayClass21_0.<GetUserAuth>b__0(IDbConnection db) at ServiceStack.Auth.OrmLiteAuthRepositoryMultitenancy2.Exec[T](Func2 fn) at ServiceStack.Auth.OrmLiteAuthRepositoryBase2.GetUserAuth(String userAuthId)
at ServiceStack.Auth.OrmLiteAuthRepositoryBase2.HasPermission(String userAuthId, String permission) at ServiceStack.AuthUserSession.HasPermission(String permission, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.<>c__DisplayClass8_0.<HasAllPermissions>b__0(String x) at System.Linq.Enumerable.All[TSource](IEnumerable1 source, Func2 predicate) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IRequest req, IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.Execute(IRequest req, IResponse res, Object requestDto) at ServiceStack.RequestFilterAttribute.RequestFilter(IRequest req, IResponse res, Object requestDto) at ServiceStack.Host.ServiceRunner1.Execute(IRequest request, Object instance, TRequest requestDto

It looks like it’s using a disposed IDbConnection somewhere along the way, if you can put together a stand-alone repro we can take a look.

I think I’ve found the offending line.

If not this line, the connection certainly comes out of the following method closed:

Whoever resolves the User Auth Repo should be responsible for disposing it, does your GetAuthRepository() in your AppHost look like this ?

public override IAuthRepository GetAuthRepository(IRequest req = null)
{
    return req != null
        ? new OrmLiteAuthRepositoryMultitenancy(GetDbConnection(req)) //At Runtime
        : TryResolve<IAuthRepository>();                              //On Startup
}

Hi, yes my code is identical. My point is that in SessionExtensions.UpdateFromUserAuthRepo method (which is called when evaluating the RequiredPermissionAttribute), the following code is called:

  using (userAuthRepo as IDisposable)
  {
         var userAuth = userAuthRepo.GetUserAuth(session, null);
         session.UpdateSession(userAuth);
    }

This will call Dispose() on userAuthRepo, which in the case of OrmLiteAuthRepositoryMultitenancy will call _db.Close(), leaving this connection unusable.

Ok yeah the issue with that code is that it should only be disposing the Auth Repo if it resolves a new one which is resolved with this commit.

This change is available from v4.5.13 that’s now available on MyGet.

Awesome. Many thanks.

G

Hi,

Since upgrading to 4.5.13 via myget, typescript definitions are now including types not exposed via service interface: e.g. IOrmLiteDialectProvider.

I have tried excluding these via:

nativeTypes.MetadataTypesConfig.IgnoreTypesInNamespaces = new[] {"ServiceStack.OrmLite"}.ToList();

but to no avail. I do have types with SqlExpression as properties, but they are excluded via [DataContract] & not having [DataMember] attributes & these have been in place for ages. Has anything changed in 4.5.13 wrt what types exposed?

Please provide the original DTO and the generated TypeScript.

In future can you please create a new POST if the question is non-related to the original post.

Apologies, will do.

Service method returns list of MapViewBase derivatives:

   using System.Collections.Generic;
  using System.Linq;
  using System.Runtime.Serialization;
  using HarbourAssist.Infrastructure.Entities;
  using ServiceStack.Data;
  using ServiceStack.OrmLite;

namespace HarbourAssist.Dtos.Data.Geo
{
[DataContract]
public abstract class MapViewBase : IMapView
{
    public IDbConnectionFactory DbConnectionFactory { get; set; }
    [DataMember]
    public abstract string Key { get; }

    [DataMember]
    public abstract string MapPopupView { get; }

    public abstract Dictionary<string, MapSqlExpression<Mooring>> Icons { get; }
    public abstract Dictionary<string, MapSqlExpression<Mooring>> Colours { get; }
    public abstract Dictionary<string, SqlExpression<Mooring>> Filters { get; }

    [DataMember]
    public List<string> FilterNames => Filters?.Select(d => d.Key).ToList();

    [DataMember]
    public Dictionary<string, string> IconLegendInfo  => Icons?.ToDictionary(d => d.Key, d => d.Value.LegendText);

    [DataMember]
    public Dictionary<string, string> ColourLegendInfo  => Colours?.ToDictionary(d => d.Key, d => d.Value.LegendText);

    [DataMember]
    public abstract bool ShowDatePicker { get; }

    [DataMember]
    public abstract bool IsDraggable { get; }
   }
}

MapSqlExpression is just:

 using ServiceStack.OrmLite;

namespace HarbourAssist.Dtos
{
    public class MapSqlExpression<T>
    {
        public string LegendText { get; set; }
        public SqlExpression<T> Expression { get; set; }
    }
}

Re. generated typescirpt, can I email you this for the sake of not exposing entire app object structure?

That’s not a DTO, it contains IDbConnectionFactory dependencies and non-serializable classes like SqlExpression<Mooring>.

Interfaces are now being generated in DTOs, what’s the definition of IMapView?

Yes I appreciate that, but I thought that the DataContract would (and has) stopped anything functional being serialised, IMapView is below. I will refactor all out to have a clean DTO as this should resolve?

namespace HarbourAssist.Dtos.Data.Geo
{
   public interface IMapView : IResolvable
    {
        string MapPopupView { get; }
        Dictionary<string, MapSqlExpression<Mooring>> Icons { get; }
        Dictionary<string, MapSqlExpression<Mooring>> Colours { get; }
        Dictionary<string, SqlExpression<Mooring>> Filters { get; }
        List<string> FilterNames { get; }
        Dictionary<string, string> IconLegendInfo { get;}
    }
}

That looks like the issue then, since Interfaces are now being generated and your interface contains non-serializable types. You can disable interfaces from being generated with:

var nativeTypes = this.GetPlugin<NativeTypesFeature>();
nativeTypes.MetadataTypesConfig.ExcludeImplementedInterfaces = true;

Thansk for help. appreciated. It’s a note to myself not to be lazy and keep DTOs clean.