fix: isolate journal storage dependency in sandbox

This commit is contained in:
Meik
2026-07-01 00:36:01 +02:00
parent 62a44568d1
commit d472923442
2 changed files with 63 additions and 3 deletions

View File

@@ -13,7 +13,7 @@
<EnableDefaultCompileItems>false</EnableDefaultCompileItems> <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<M42ExtensionId>6673a25d-33d6-4072-91d9-abed4be1a966</M42ExtensionId> <M42ExtensionId>6673a25d-33d6-4072-91d9-abed4be1a966</M42ExtensionId>
<M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern> <M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern>
<M42PackageVersion>1.4.0.28</M42PackageVersion> <M42PackageVersion>1.4.0.29</M42PackageVersion>
<M42BuildPackage>true</M42BuildPackage> <M42BuildPackage>true</M42BuildPackage>
</PropertyGroup> </PropertyGroup>

View File

@@ -43,6 +43,8 @@ namespace C4IT.F4SD
private readonly F4SDHelperService _f4stHelperService; private readonly F4SDHelperService _f4stHelperService;
private const string TeamsNotificationServiceTypeName = "Matrix42.Contracts.Platform.MsTeams.ITeamsNotificationService";
private const string StorageServiceTypeName = "Matrix42.StorageService.Contracts.IStorageService";
public string BaseUrl => Request?.RequestUri == null ? string.Empty : $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}"; public string BaseUrl => Request?.RequestUri == null ? string.Empty : $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}";
public string EndpointBaseUrl => $"{BaseUrl}/m42Services/api/c4itf4sdwebapi"; public string EndpointBaseUrl => $"{BaseUrl}/m42Services/api/c4itf4sdwebapi";
@@ -132,9 +134,9 @@ namespace C4IT.F4SD
private object ResolveJournalServiceConstructorParameter(System.Reflection.ParameterInfo parameter) private object ResolveJournalServiceConstructorParameter(System.Reflection.ParameterInfo parameter)
{ {
if (parameter.ParameterType == typeof(IDependencyResolver)) if (parameter.ParameterType == typeof(IDependencyResolver))
return _resolver; return CreateJournalDependencyResolver(_resolver);
if (parameter.ParameterType.FullName == "Matrix42.Contracts.Platform.MsTeams.ITeamsNotificationService") if (parameter.ParameterType.FullName == TeamsNotificationServiceTypeName || parameter.ParameterType.FullName == StorageServiceTypeName)
return CreateNoOpInterfaceProxy(parameter.ParameterType); return CreateNoOpInterfaceProxy(parameter.ParameterType);
var service = _resolver.TryGet(parameter.ParameterType); var service = _resolver.TryGet(parameter.ParameterType);
@@ -144,6 +146,13 @@ namespace C4IT.F4SD
throw new InvalidOperationException($"Required JournalService constructor dependency is not registered: {parameter.ParameterType.FullName} ({parameter.Name})."); throw new InvalidOperationException($"Required JournalService constructor dependency is not registered: {parameter.ParameterType.FullName} ({parameter.Name}).");
} }
private static IDependencyResolver CreateJournalDependencyResolver(IDependencyResolver resolver)
{
var proxy = DispatchProxy.Create<IDependencyResolver, JournalDependencyResolverProxy>();
((JournalDependencyResolverProxy)(object)proxy).Inner = resolver;
return proxy;
}
private static Type FindLoadedType(string fullName) private static Type FindLoadedType(string fullName)
{ {
return AppDomain.CurrentDomain return AppDomain.CurrentDomain
@@ -163,6 +172,57 @@ namespace C4IT.F4SD
.Invoke(null, null); .Invoke(null, null);
} }
public class JournalDependencyResolverProxy : DispatchProxy
{
public IDependencyResolver Inner { get; set; }
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var requestedType = GetRequestedServiceType(targetMethod, args);
if (requestedType?.FullName == StorageServiceTypeName)
return CreateResolverResultForStorageService(targetMethod, requestedType);
try
{
return targetMethod.Invoke(Inner, args);
}
catch (TargetInvocationException ex) when (ex.InnerException != null)
{
throw ex.InnerException;
}
}
}
private static Type GetRequestedServiceType(MethodInfo targetMethod, object[] args)
{
if (targetMethod.IsGenericMethod && targetMethod.GetGenericArguments().Length > 0)
return targetMethod.GetGenericArguments()[0];
if (args?.Length > 0 && args[0] is Type type)
return type;
return null;
}
private static object CreateResolverResultForStorageService(MethodInfo targetMethod, Type requestedType)
{
if (targetMethod.Name.StartsWith("IsRegistered", StringComparison.Ordinal))
return true;
if (targetMethod.Name.Contains("All"))
return CreateEmptyEnumerable(targetMethod.ReturnType, requestedType);
return CreateNoOpInterfaceProxy(requestedType);
}
private static object CreateEmptyEnumerable(Type returnType, Type itemType)
{
if (returnType.IsGenericType)
return Array.CreateInstance(returnType.GetGenericArguments()[0], 0);
return Array.CreateInstance(itemType ?? typeof(object), 0);
}
public class NoOpInterfaceProxy : DispatchProxy public class NoOpInterfaceProxy : DispatchProxy
{ {
public NoOpInterfaceProxy() public NoOpInterfaceProxy()