From c41537b56f463a316d7fab94e250302839c0fe67 Mon Sep 17 00:00:00 2001 From: Rene Evertz Date: Tue, 25 Feb 2025 11:50:47 +0100 Subject: [PATCH] Kann jetzt TemplateURI /= Methodname finden --- Host/Web.config | 4 +- .../Security/SecurityContextInitializer.cs | 19 +++++- Service/Service.csproj | 1 + .../AdminMultitenancyContextInitializer.cs | 55 ++++++++------- .../JsonError/JsonErrorHandler.cs | 4 ++ Service/ServiceContracts/IAdminService.cs | 4 ++ .../ServiceImplementations/AdminServiceImp.cs | 28 +++++++- Service/ServiceUtils/ServiceHelper.cs | 67 +++++++++++++++---- Service/ServiceUtils/UriTemplateResolver.cs | 46 +++++++++++++ 9 files changed, 180 insertions(+), 48 deletions(-) create mode 100644 Service/ServiceUtils/UriTemplateResolver.cs diff --git a/Host/Web.config b/Host/Web.config index b183fe83f..6e8ddf61d 100644 --- a/Host/Web.config +++ b/Host/Web.config @@ -216,12 +216,12 @@ - - + + diff --git a/Service/Security/SecurityContextInitializer.cs b/Service/Security/SecurityContextInitializer.cs index ecd2cb5c2..d81c3604b 100644 --- a/Service/Security/SecurityContextInitializer.cs +++ b/Service/Security/SecurityContextInitializer.cs @@ -122,7 +122,7 @@ namespace BeWo.Service.Security } } - private bool HasMethodAuthorization(ApplicationUser lUser, string methodName, Message pMessage) + private bool HasMethodAuthorization(ApplicationUser pUser, string methodName, Message pMessage) { if (ALLOW_ONLY_WITH_LOGIN.Contains(methodName)) { @@ -133,11 +133,24 @@ namespace BeWo.Service.Security // Vergessen neue Methode einzutragen? } - var rights = Utils.GetGrantedRights(lUser); + var rights = Utils.GetGrantedRights(pUser); + + // Finde Action + var lTemp = pMessage.Headers.Action?.Split("/"); + + if (lTemp is null) + lTemp = pMessage.Headers.To.Segments.ToList(); + + if (lTemp is null) + throw new ArgumentException("Kann Action nicht finden"); + + // Extrahiere MethodeName + ServiceInterface + string lMethodName = lTemp[lTemp.Count - 1].Trim('/'); + string lServiceInterface = lTemp[lTemp.Count - 2].Trim('/'); try { - var attribute = pMessage.GetCustomAttribute(); + var attribute = ServiceHelper.GetCustomAttribute(lServiceInterface, lMethodName); if (attribute != null) { return attribute.HasPermission(rights); diff --git a/Service/Service.csproj b/Service/Service.csproj index d74c33099..a20ad2ead 100644 --- a/Service/Service.csproj +++ b/Service/Service.csproj @@ -530,6 +530,7 @@ + diff --git a/Service/ServiceBehavior/AdminMultitenancyContextInitializer.cs b/Service/ServiceBehavior/AdminMultitenancyContextInitializer.cs index 718d34335..e228ffe0a 100644 --- a/Service/ServiceBehavior/AdminMultitenancyContextInitializer.cs +++ b/Service/ServiceBehavior/AdminMultitenancyContextInitializer.cs @@ -31,38 +31,37 @@ namespace BeWo.Service.ServiceBehavior { string lTenant = null; - try + // RequireNoTenant + var lTemp = ServiceHelper.GetCustomAttribute(pChannel.LocalAddress.Uri, pMessage.Headers.To); + if (lTemp is object) { - // RequireNoTenant - var lTemp = pMessage.GetCustomAttribute(); - if (lTemp is object) - { - return null; - } - - // Hole tenant aus Query - if (pMessage.Properties?.Via is Uri uri) - { - var query = HttpUtility.ParseQueryString(uri.Query); - var tenant = query["tenant"]; - - lTenant = tenant; - } - - // Wenn kein Tenant gefunden wird, - if (string.IsNullOrWhiteSpace(lTenant)) - { - throw new ArgumentException($"Zugriff verweigert. Tenant (\'{lTenant}\') darf nicht leer sein.", nameof(lTenant)); - } - - var lExt = new MultitenancyOperationContextExt { Tenant = lTenant }; - OperationContext.Current.Extensions.Add(lExt); - return lExt; + return null; } - catch (Exception e) + + //// Hole tenant aus Query + if (pMessage.Properties?.Via is Uri uri) { - throw Utils.CreateBeWoFaultException(e); + var query = HttpUtility.ParseQueryString(uri.Query); + var tenant = query["tenant"]; + + lTenant = tenant; } + + // Hole tenant aus Header + if (string.IsNullOrWhiteSpace(lTenant)) + { + + } + + // Wenn kein Tenant gefunden wird, + if (string.IsNullOrWhiteSpace(lTenant)) + { + throw new ArgumentException($"Zugriff verweigert. Tenant (\'{lTenant}\') darf nicht leer sein.", nameof(lTenant)); + } + + var lExt = new MultitenancyOperationContextExt { Tenant = lTenant }; + OperationContext.Current.Extensions.Add(lExt); + return lExt; } } } diff --git a/Service/ServiceBehavior/JsonError/JsonErrorHandler.cs b/Service/ServiceBehavior/JsonError/JsonErrorHandler.cs index f8f7d7f0f..895c8010b 100644 --- a/Service/ServiceBehavior/JsonError/JsonErrorHandler.cs +++ b/Service/ServiceBehavior/JsonError/JsonErrorHandler.cs @@ -18,6 +18,9 @@ namespace BeWo.Service.ServiceBehavior.JsonError [DataMember] public string Message { get; set; } + [DataMember] + public string StackTrace { get; set; } + [DataMember] public string ExceptionType { get; set; } } @@ -30,6 +33,7 @@ namespace BeWo.Service.ServiceBehavior.JsonError var jsonError = new JsonError { Message = error.Message, + StackTrace = error.StackTrace, ExceptionType = error.GetType().Name }; diff --git a/Service/ServiceContracts/IAdminService.cs b/Service/ServiceContracts/IAdminService.cs index 36aab6c82..c11ee79c9 100644 --- a/Service/ServiceContracts/IAdminService.cs +++ b/Service/ServiceContracts/IAdminService.cs @@ -21,5 +21,9 @@ namespace BeWo.Service.ServiceContracts [WebInvoke(UriTemplate = "/Echo/{echo}", Method ="POST", ResponseFormat = WebMessageFormat.Json)] [RequireNoTenant] string Echo(string echo); + + [OperationContract] + [WebInvoke(UriTemplate = "/GetGkvSum?start={start}&end={end}", Method = "POST", ResponseFormat = WebMessageFormat.Json)] + object GetGkvAbrechnungSumme(DateTime start, DateTime end); } } diff --git a/Service/ServiceImplementations/AdminServiceImp.cs b/Service/ServiceImplementations/AdminServiceImp.cs index cfb828905..e45869410 100644 --- a/Service/ServiceImplementations/AdminServiceImp.cs +++ b/Service/ServiceImplementations/AdminServiceImp.cs @@ -1,4 +1,6 @@ -using BeWo.Service.ServiceContracts; +using BeWo.Data.Access; +using BeWo.Service.ServiceContracts; +using DevExpress.Pdf.Native.BouncyCastle.Ocsp; using System; using System.Collections.Generic; using System.Linq; @@ -20,5 +22,29 @@ namespace BeWo.Service.ServiceImplementations { return echo; } + + public object GetGkvAbrechnungSumme(DateTime start, DateTime end) + { + if(start == default(DateTime)) + { + return "Start darf nicht default(DateTime) sein"; + } + + if(end == default(DateTime)) + { + return "End darf nicht default(DateTime) sein"; + } + + var sum = DAOFactory.ScriptDAO.GetGkvSumByDateRange(start, end); + + if (sum is decimal s) + { + return sum; + } + else + { + return "Sum ist null"; + }; + } } } diff --git a/Service/ServiceUtils/ServiceHelper.cs b/Service/ServiceUtils/ServiceHelper.cs index 1602264b2..711348316 100644 --- a/Service/ServiceUtils/ServiceHelper.cs +++ b/Service/ServiceUtils/ServiceHelper.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.ServiceModel.Channels; using System.Text; using System.Threading.Tasks; +using BeWo.Service.ServiceContracts; using BS.Shared.Attributes; using BS.Shared.Extensions; using NHibernate.Hql.Ast.ANTLR.Tree; @@ -14,25 +15,63 @@ namespace BeWo.Service.ServiceUtils { public static class ServiceHelper { - public static T GetCustomAttribute(this Message pMessage) where T : Attribute + public static T GetCustomAttribute(Uri baseAddress, Uri request) where T : Attribute { - // Finde Action - var lTemp = pMessage.Headers.Action?.Split("/"); + // Hole Interface + string lInterface = null; + var segments = baseAddress.Segments; + for (int i = 0; i < segments.Length; i++) + { + var seg = segments[i].Trim('/'); - if (lTemp is null) - lTemp = pMessage.Headers.To.Segments.ToList(); + if (seg.EndsWith(".svc")) + { + lInterface = seg.Substring(0, seg.Length - 4); + } + } - if (lTemp is null) - throw new ArgumentException("Kann Action nicht finden"); + // Falls kein Interface gefunden wird + if (string.IsNullOrWhiteSpace(lInterface) ) + { + throw new ArgumentException($"Zugriff verweigert. Interface unbekannt"); + } - // Extrahiere MethodeName + ServiceInterface - string lMethodName = lTemp[lTemp.Count - 1].Trim('/'); - string lServiceInterface = lTemp[lTemp.Count - 2].Trim('/'); - - // Hole entsprechende Methode - var name = $"BeWo.Service.ServiceContracts.I{lServiceInterface}"; + // Wird für URLTemplate != Methodname verwendet + var name = $"BeWo.Service.ServiceContracts.I{lInterface}"; var t = Type.GetType(name); - var methodInfo = t.GetMethod(lMethodName); + var resolver = new UriTemplateResolver(baseAddress, t); + var method = resolver.ResolveMethod(request.AbsoluteUri); + var methodInfo = t.GetMethod(method); + + // Rückgabe + return getCustomAttribute(methodInfo); + } + + public static T GetCustomAttribute(string pServiceInterface, string pMethodName) where T : Attribute + { + MethodInfo methodInfo = null; + + try + { + // Hole entsprechende Methode + var name = $"BeWo.Service.ServiceContracts.I{pServiceInterface}"; + var t = Type.GetType(name); + methodInfo = t.GetMethod(pMethodName); + } + catch (Exception) + { + throw new ArgumentException($"Zugriff verweigert. Interface oder Methode unbekannt"); + } + + return getCustomAttribute(methodInfo); + } + + private static T getCustomAttribute(MethodInfo methodInfo) where T : Attribute + { + if (methodInfo == null) + { + throw new ArgumentException($"Zugriff verweigert. Interface oder Methode unbekannt"); + } // Hole Custome Attribute var attribute = methodInfo.GetCustomAttribute(); diff --git a/Service/ServiceUtils/UriTemplateResolver.cs b/Service/ServiceUtils/UriTemplateResolver.cs new file mode 100644 index 000000000..6bd3f170b --- /dev/null +++ b/Service/ServiceUtils/UriTemplateResolver.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.ServiceModel.Web; +using System.Text; +using System.Threading.Tasks; + +namespace BeWo.Service.ServiceUtils +{ + public class UriTemplateResolver + { + private UriTemplateTable _uriTemplateTable; + + public UriTemplateResolver(Uri baseAddress, Type serviceType) + { + _uriTemplateTable = new UriTemplateTable(baseAddress); + + foreach (var method in serviceType.GetMethods()) + { + var webGet = method.GetCustomAttribute(); + var webInvoke = method.GetCustomAttribute(); + + if (webGet != null) + { + _uriTemplateTable.KeyValuePairs.Add(new KeyValuePair( + new UriTemplate(webGet.UriTemplate), method.Name)); + } + else if (webInvoke != null) + { + _uriTemplateTable.KeyValuePairs.Add(new KeyValuePair( + new UriTemplate(webInvoke.UriTemplate), method.Name)); + } + } + + _uriTemplateTable.MakeReadOnly(false); + } + + public string ResolveMethod(string requestUri) + { + var match = _uriTemplateTable.MatchSingle(new Uri(requestUri)); + return match?.Data as string; + } + } + +}