/// <inheritdoc/> public Task <bool> AuthorizeAsync(SubmitContext context, ChangeSetItem item, CancellationToken cancellationToken) { Ensure.NotNull(context, nameof(context)); var result = true; var returnType = typeof(bool); var dataModification = (DataModificationItem)item; var methodName = ConventionBasedMethodNameFactory.GetEntitySetMethodName(dataModification, RestierPipelineState.Authorization); var method = targetType.GetQualifiedMethod(methodName); if (method != null && method.IsFamily && method.ReturnType == returnType) { object target = null; if (!method.IsStatic) { target = context.GetApiService <ApiBase>(); if (target == null || !targetType.IsInstanceOfType(target)) { return(Task.FromResult(result)); } } var parameters = method.GetParameters(); if (parameters.Length == 0) { result = (bool)method.Invoke(target, null); } } return(Task.FromResult(result)); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="item"></param> /// <param name="pipelineState"></param> /// <returns></returns> private Task InvokeProcessorMethodAsync(SubmitContext context, ChangeSetItem item, RestierPipelineState pipelineState) { var dataModification = (DataModificationItem)item; var expectedMethodName = ConventionBasedMethodNameFactory.GetEntitySetMethodName(dataModification, pipelineState); var expectedMethod = targetApiType.GetQualifiedMethod(expectedMethodName); if (expectedMethod == null) { var actualMethodName = expectedMethodName.Replace(dataModification.ExpectedResourceType.Name, dataModification.ResourceSetName); var actualMethod = targetApiType.GetQualifiedMethod(actualMethodName); if (actualMethod != null) { Trace.WriteLine($"Restier Filter expected'{expectedMethodName}' but found '{actualMethodName}'. Your method will not be called until you correct the method name."); } return(Task.CompletedTask); } if (!expectedMethod.IsFamily && !expectedMethod.IsFamilyOrAssembly) { Trace.WriteLine($"Restier Filter found '{expectedMethod}' but it is inaccessible due to its protection level. Your method will not be called until you change it to 'protected internal'."); return(Task.CompletedTask); } if (expectedMethod.ReturnType != typeof(void) && !typeof(Task).IsAssignableFrom(expectedMethod.ReturnType)) { Trace.WriteLine($"Restier Filter found '{expectedMethod}' but it does not return void or a Task. Your method will not be called until you correct the return type."); return(Task.CompletedTask); } object target = null; if (!expectedMethod.IsStatic) { target = context.Api; if (target == null || !targetApiType.IsInstanceOfType(target)) { Trace.WriteLine("The Restier API is of the incorrect type."); return(Task.CompletedTask); } } var parameters = GetParameters(item); var methodParameters = expectedMethod.GetParameters(); if (ParametersMatch(methodParameters, parameters)) { var result = expectedMethod.Invoke(target, parameters); if (result is Task resultTask) { return(resultTask); } } Trace.WriteLine($"Restier Authorizer found '{expectedMethod}', but it has an incorrect number of arguments or the types don't match. The number of arguments should be 1."); return(Task.CompletedTask); }
/// <inheritdoc/> public Task <bool> AuthorizeAsync(SubmitContext context, ChangeSetItem item, CancellationToken cancellationToken) { Ensure.NotNull(context, nameof(context)); Ensure.NotNull(item, nameof(item)); var result = true; var returnType = typeof(bool); var dataModification = (DataModificationItem)item; var methodName = ConventionBasedMethodNameFactory.GetEntitySetMethodName(dataModification, RestierPipelineState.Authorization); var method = targetApiType.GetQualifiedMethod(methodName); if (method == null) { return(Task.FromResult(result)); } if (!method.IsFamily && !method.IsFamilyOrAssembly) { Trace.WriteLine($"Restier Authorizer found '{methodName}' but it is unaccessible due to its protection level. Your method will not be called until you change it to 'protected internal'."); return(Task.FromResult(result)); } if (method.ReturnType != returnType) { Trace.WriteLine($"Restier Authorizer found '{methodName}' but it does not return a boolean value. Your method will not be called until you correct the return type."); return(Task.FromResult(result)); } object target = null; if (!method.IsStatic) { target = context.Api; if (!targetApiType.IsInstanceOfType(target)) { Trace.WriteLine("The Restier API is of the incorrect type."); return(Task.FromResult(result)); } } var parameters = method.GetParameters(); if (parameters.Length == 0) { result = (bool)method.Invoke(target, null); } Trace.WriteLine($"Restier Authorizer found '{methodName}', but it has an incorrect number of arguments. The number of arguments should be 0."); return(Task.FromResult(result)); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="item"></param> /// <param name="pipelineState"></param> /// <returns></returns> private Task InvokeProcessorMethodAsync(SubmitContext context, ChangeSetItem item, RestierPipelineState pipelineState) { var dataModification = (DataModificationItem)item; var expectedMethodName = ConventionBasedMethodNameFactory.GetEntitySetMethodName(dataModification, pipelineState); var expectedMethod = targetApiType.GetQualifiedMethod(expectedMethodName); if (!IsUsable(expectedMethod)) { if (expectedMethod != null) { Trace.WriteLine($"Restier Filter found '{expectedMethodName}' but it is unaccessible due to its protection level. Your method will not be called until you change it to 'protected internal'."); } else { var actualMethodName = expectedMethodName.Replace(dataModification.ExpectedResourceType.Name, dataModification.ResourceSetName); var actualMethod = targetApiType.GetQualifiedMethod(actualMethodName); if (actualMethod != null) { Trace.WriteLine($"BREAKING: Restier Filter expected'{expectedMethodName}' but found '{actualMethodName}'. Your method will not be called until you correct the method name."); } } } else { object target = null; if (!expectedMethod.IsStatic) { target = context.Api; if (target == null || !targetApiType.IsInstanceOfType(target)) { return(Task.WhenAll()); } } var parameters = GetParameters(item); var methodParameters = expectedMethod.GetParameters(); if (ParametersMatch(methodParameters, parameters)) { var result = expectedMethod.Invoke(target, parameters); if (result is Task resultTask) { return(resultTask); } } } return(Task.WhenAll()); }
private Expression AppendOnFilterExpression(QueryExpressionContext context, IEdmEntitySet entitySet, IEdmEntityType entityType) { var expectedMethodName = ConventionBasedMethodNameFactory.GetEntitySetMethodName(entitySet, RestierPipelineState.Submit, RestierEntitySetOperation.Filter); var expectedMethod = targetType.GetQualifiedMethod(expectedMethodName); if (expectedMethod == null || (!expectedMethod.IsFamily && !expectedMethod.IsFamilyOrAssembly)) { if (expectedMethod != null) { Debug.WriteLine($"Restier Filter found '{expectedMethodName}' but it is unaccessible due to its protection level. Change it to be 'protected internal'."); } else { var actualMethodName = expectedMethodName.Replace(entitySet.Name, entityType.Name); var actualMethod = targetType.GetQualifiedMethod(actualMethodName); if (actualMethod != null) { Debug.WriteLine($"BREAKING: Restier Filter expected'{expectedMethodName}' but found '{actualMethodName}'. Please correct the method name."); } } return(null); } var parameter = expectedMethod.GetParameters().SingleOrDefault(); if (parameter == null || parameter.ParameterType != expectedMethod.ReturnType) { return(null); } object apiBase = null; if (!expectedMethod.IsStatic) { apiBase = context.QueryContext.Api; if (apiBase == null || !targetType.IsInstanceOfType(apiBase)) { return(null); } } // The LINQ expression built below has three cases // For navigation property, just add a where condition from OnFilter method // For collection property, will be like "Param_0.Prop.AsQueryable().Where(...)" // For collection property of derived type, will be like "Param_0.Prop.AsQueryable().Where(...).OfType()" var returnType = context.VisitedNode.Type.FindGenericType(typeof(IQueryable <>)); var enumerableQueryParameter = (object)context.VisitedNode; Type elementType = null; if (returnType == null) { // This means append for properties model reference var collectionType = context.VisitedNode.Type.FindGenericType(typeof(ICollection <>)); if (collectionType == null) { return(null); } elementType = collectionType.GetGenericArguments()[0]; returnType = typeof(IQueryable <>).MakeGenericType(elementType); enumerableQueryParameter = Expression.Call(ExpressionHelperMethods.QueryableAsQueryableGeneric.MakeGenericMethod(elementType), context.VisitedNode); } else { elementType = returnType.GetGenericArguments()[0]; } var queryType = typeof(EnumerableQuery <>).MakeGenericType(elementType); var query = Activator.CreateInstance(queryType, enumerableQueryParameter); if (!(expectedMethod.Invoke(apiBase, new object[] { query }) is IQueryable result)) { return(null); } if (expectedMethod.ReturnType == returnType) { if (result != query) { return(result.Expression); } } else { // This means calling onFilter against derived type and based type is returned // Need to convert back to derived type with OfType result = ExpressionHelpers.OfType(result, elementType); return(result.Expression); } return(null); }