private bool FilterByPolicies(OperationInspector inspector, ODataOperationMethodDescriptor action, Content content) { if (action.OperationInfo.Policies.Length == 0) { return(true); } //TODO:~ set HttpContext in OperationCallingContext var context = new OperationCallingContext(content, action.OperationInfo); switch (inspector.CheckPolicies(action.OperationInfo.Policies, context)) { case OperationMethodVisibility.Invisible: return(false); case OperationMethodVisibility.Disabled: // according to the policy this action is visible to the user but cannot be executed action.Forbidden = true; break; case OperationMethodVisibility.Enabled: break; default: throw new ArgumentOutOfRangeException(); } return(true); }
public static async Task <object> InvokeAsync(OperationCallingContext context) { var parameters = PrepareInvoke(context); try { var invokeResult = context.Operation.Method.Invoke(null, parameters); var invokeResultType = invokeResult.GetType(); var awaitable = (Task)invokeResult; await awaitable; if (invokeResultType.IsGenericType) { // It is impossible to convert to the target type (Task<??>) so getting result with reflection. var resultProperty = invokeResultType.GetProperty("Result"); var result = resultProperty?.GetValue(awaitable); return(result); } // Non-generic Task have no result. return(null); } catch (TargetInvocationException e) { if (e.InnerException == null) { throw; } throw e.InnerException; } }
public virtual OperationMethodVisibility CheckPolicies(string[] policies, OperationCallingContext context) { if (User.Current.Id == Identifiers.SystemUserId) { return(OperationMethodVisibility.Enabled); } var visibilityResult = OperationMethodVisibility.Enabled; foreach (var policyName in policies) { if (!OperationCenter.Policies.TryGetValue(policyName, out var policy)) { throw new UnknownOperationMethodPolicyException("Policy not found: " + policyName); } // Check visibility according to the current policy. If this policy is more // restrictive than previous ones then degrade the final result value; var visibility = policy.GetMethodVisibility(User.Current, context); if (visibility < visibilityResult) { visibilityResult = visibility; } // no need to execute remaining policies: the action is already inaccessible if (visibilityResult == OperationMethodVisibility.Invisible) { return(visibilityResult); } } return(visibilityResult); }
private static object[] PrepareInvoke(OperationCallingContext context) { var method = context.Operation.Method; var methodParams = method.GetParameters(); var paramValues = new object[methodParams.Length]; paramValues[0] = context.Content; for (int i = 1; i < methodParams.Length; i++) { if (!context.Parameters.TryGetValue(methodParams[i].Name, out paramValues[i])) { if (methodParams[i].ParameterType == typeof(HttpContext)) { paramValues[i] = context.HttpContext; } else if (methodParams[i].ParameterType == typeof(ODataRequest)) { paramValues[i] = context.HttpContext.GetODataRequest(); } else if (methodParams[i].ParameterType == typeof(IConfiguration)) { paramValues[i] = context.ApplicationConfiguration; } else { paramValues[i] = methodParams[i].DefaultValue; } } } var inspector = OperationInspector.Instance; var operation = context.Operation; var user = User.Current; // ContentType, role, permission verification is not necessary here because the method candidates are already filtered. // The method call is not allowed if there is no authorization rule. var roles = operation.Roles; var permissions = operation.Permissions; var policies = context.Operation.Policies; if (user.Id != Identifiers.SystemUserId) { if (roles.Length + permissions.Length + policies.Length == 0) { throw new UnauthorizedAccessException(); } } // Execute the code-based policies (if there is any). if (policies.Length > 0 && inspector.CheckPolicies(policies, context) < OperationMethodVisibility.Enabled) { throw new AccessDeniedException(null, null, 0, null, null); } return(paramValues); }
private static bool TryParseParameters(OperationInfo candidate, Content content, ODataParameterCollection odataParameters, bool strict, out OperationCallingContext context) { context = new OperationCallingContext(content, candidate); // If there is no any request parameter, the validity of candidate depends on the required parameter count. if (odataParameters == null) { return(candidate.RequiredParameterNames.Length == 0); } // Foreach all optional parameters of the method for (int i = 0; i < candidate.OptionalParameterNames.Length; i++) { var name = candidate.OptionalParameterNames[i]; // If does not exist in the request: continue (move the next parameter) if (!odataParameters.TryGetValue(name, out var value)) { continue; } // If parse request by parameter"s type is not successful: return false var type = candidate.OptionalParameterTypes[i]; if (!TryParseParameter(type, value, strict, out var parsed)) { return(false); } // Add parameter name/value to the calling context context.SetParameter(name, parsed); } // Foreach all required parameters of the method for (int i = 0; i < candidate.RequiredParameterNames.Length; i++) { var name = candidate.RequiredParameterNames[i]; var value = odataParameters[name]; var type = candidate.RequiredParameterTypes[i]; // If parse request by parameter"s type is not successful: return false if (!TryParseParameter(type, value, strict, out var parsed)) { return(false); } // Add parameter name/value to the calling context context.SetParameter(name, parsed); } return(true); }
/* ===================================================================================== INVOKE */ public static object Invoke(OperationCallingContext context) { var parameters = PrepareInvoke(context); try { return(context.Operation.Method.Invoke(null, parameters)); } catch (TargetInvocationException e) { if (e.InnerException == null) { throw; } throw e.InnerException; } }
public static async Task <object> InvokeAsync(OperationCallingContext context) { var parameters = PrepareInvoke(context); try { dynamic awaitable = context.Operation.Method.Invoke(null, parameters); await awaitable; return(awaitable.GetAwaiter().GetResult()); } catch (TargetInvocationException e) { if (e.InnerException == null) { throw; } throw e.InnerException; } }
public ODataOperationMethodExecutor(OperationCallingContext context) { Method = context; }
public OperationMethodVisibility GetMethodVisibility(IUser user, OperationCallingContext context) { return(SavingAction.IsValidVersioningAction(context.Content?.ContentHandler, context.Operation.Name) ? OperationMethodVisibility.Enabled : OperationMethodVisibility.Invisible); }
public OperationMethodVisibility GetMethodVisibility(IUser user, OperationCallingContext context) { return(Callback(user, context)); }