示例#1
0
        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);
        }
示例#2
0
        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;
            }
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        /* ===================================================================================== 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;
            }
        }
示例#7
0
        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);
 }
示例#10
0
 public OperationMethodVisibility GetMethodVisibility(IUser user, OperationCallingContext context)
 {
     return(Callback(user, context));
 }