예제 #1
0
파일: Manager.cs 프로젝트: arychj/Legion
        /// <summary>
        /// Gets the result from the requested handler
        /// </summary>
        /// <param name="request">The LegionRequest object to process</param>
        /// <param name="services">Dictionary of the available Services</param>
        /// <returns>A string representation of the XML result</returns>
        private static Reply GetReply(Request request, Dictionary <string, Service> services)
        {
            Cache.Refresh();
            ResultCache.TryExpire();

            Reply reply = new Reply(request);

            Service  service = null; Method method = null;
            DateTime dtprocessed   = DateTime.Now;
            TimeSpan executionTime = TimeSpan.Zero;

            try {
                if (!request.RateLimit.IsExceeded)
                {
                    request.RateLimit.BitchSlap();

                    //identify service.method call
                    if (request.APIKey.Key != null)
                    {
                        if (!request.APIKey.IsRevoked)
                        {
                            if (request.APIKey.IsValid)
                            {
                                if (request.IsServiceToService || request.Application.HasValidSourceIP(request.Requestor.HostIPAddress))
                                {
                                    if (request.ServiceKey != null)
                                    {
                                        if (services.ContainsKey(request.ServiceKey))
                                        {
                                            service = services[request.ServiceKey];
                                            if (request.IsServiceToService || service.HasValidSourceIP(request.Requestor.HostIPAddress))
                                            {
                                                if (request.MethodKey != null)
                                                {
                                                    if (service.Open != null && service.Open.ContainsKey(request.MethodKey))
                                                    {
                                                        method = service.Open[request.MethodKey];
                                                    }
                                                    else if (service.Restricted != null && service.Restricted.ContainsKey(request.MethodKey))
                                                    {
                                                        if (request.IsServiceToService || request.Application.HasPermissionTo(request.ServiceKey, request.MethodKey))
                                                        {
                                                            method = service.Restricted[request.MethodKey];
                                                        }
                                                        else //application does not have access to this method
                                                        {
                                                            LogFault(request, reply, "InsufficientPermissions", Settings.GetString("FaultMessageInsufficientPermissions", new Dictionary <string, string>()
                                                            {
                                                                { "ApplicationName", request.Application.Name },
                                                                { "ServiceKey", request.ServiceKey },
                                                                { "MethodKey", request.MethodKey }
                                                            }));
                                                        }
                                                    }
                                                    else if (service.Special.ContainsKey(request.MethodKey))   //special method
                                                    {
                                                        method = service.Special[request.MethodKey];
                                                    }
                                                    else //method not found
                                                    {
                                                        LogFault(request, reply, "MethodNotFound", Settings.GetString("FaultMessageMethodNotFound", new Dictionary <string, string>()
                                                        {
                                                            { "ServiceKey", request.ServiceKey },
                                                            { "MethodKey", request.MethodKey }
                                                        }));
                                                    }
                                                }
                                                else //method not specified
                                                {
                                                    LogFault(request, reply, "MethodNotSpecified", Settings.GetString("FaultMessageMethodNotSpecified", new Dictionary <string, string>()
                                                    {
                                                        { "ServiceKey", request.ServiceKey }
                                                    }));
                                                }
                                            }
                                            else //invalid service source ip
                                            {
                                                LogFault(request, reply, "ServiceSourceIpInvalid", Settings.GetString("FaultMessageServiceSourceIpInvalid", new Dictionary <string, string>()
                                                {
                                                    { "HostIpAddress", request.Requestor.HostIPAddress },
                                                    { "ServiceKey", request.ServiceKey }
                                                }));
                                            }
                                        }
                                        else //service not found
                                        {
                                            LogFault(request, reply, "ServiceNotFound", Settings.GetString("FaultMessageServiceNotFound", new Dictionary <string, string>()
                                            {
                                                { "ServiceKey", request.ServiceKey }
                                            }));
                                        }
                                    }
                                    else //no service specified
                                    {
                                        LogFault(request, reply, "ServiceNotSpecified", Settings.GetString("FaultMessageServiceNotSpecified", new Dictionary <string, string>()
                                        {
                                        }));
                                    }
                                }
                                else //invalid application source ip
                                {
                                    LogFault(request, reply, "ApplicationSourceIpInvalid", Settings.GetString("FaultMessageApplicationSourceIpInvalid", new Dictionary <string, string>()
                                    {
                                        { "HostIpAddress", request.Requestor.HostIPAddress },
                                        { "ApiKey", request.APIKey.Key }
                                    }));
                                }
                            }
                            else //api key not found
                            {
                                LogFault(request, reply, "ApiKeyInvalid", Settings.GetString("FaultMessageApiKeyInvalid", new Dictionary <string, string>()
                                {
                                    { "ApiKey", request.APIKey.Key }
                                }));
                            }
                        }
                        else //api key revoked
                        {
                            LogFault(request, reply, "ApiKeyRevoked", Settings.GetString("FaultMessageApiKeyRevoked", new Dictionary <string, string>()
                            {
                                { "ApiKey", request.APIKey.Key }
                            }));
                        }
                    }
                    else //no api key specified
                    {
                        LogFault(request, reply, "ApiKeyNotSpecified", Settings.GetString("FaultMessageApiKeyNotSpecified", new Dictionary <string, string>()
                        {
                        }));
                    }
                }
                else //rate limit exceeded
                {
                    LogFault(request, reply, "RateLimitExceeded", Settings.GetString("FaultMessageRateLimitExceeded", new Dictionary <string, string>()
                    {
                        { "RateLimit", request.RateLimit.ToString() }
                    }));
                }

                //restrict public proxied requests
                if (method != null && request.IsProxied)
                {
                    if (!request.Application.IsPublic)
                    {
                        method = null;
                        LogFault(request, reply, "ApplicationNotPublic", Settings.GetString("FaultMessageApplicationNotPublic", new Dictionary <string, string>()
                        {
                            { "ApiKey", request.APIKey.Key }
                        }));
                    }
                    else if (!(service.IsPublic || method.IsPublic))
                    {
                        method = null;
                        LogFault(request, reply, "MethodNotPublic", Settings.GetString("FaultMessageMethodNotPublic", new Dictionary <string, string>()
                        {
                            { "MethodKey", request.MethodKey }
                        }));
                    }
                }

                if (method != null)
                {
                    if (request.Requestor.Account == null)   //check for auth token if required
                    {
                        if (method.IsAuthenticatedUserRequired)
                        {
                            method = null;
                            LogFault(request, reply, "AuthenticatedUserRequiredForMethod", Settings.GetString("FaultMessageMethodAuthenticatedUserRequired", new Dictionary <string, string>()
                            {
                                { "MethodKey", request.MethodKey }
                            }));
                        }
                        else if (service.IsAuthenticatedUserRequired)
                        {
                            method = null;
                            LogFault(request, reply, "AuthenticatedUserRequiredForService", Settings.GetString("FaultMessageServiceAuthenticatedUserRequired", new Dictionary <string, string>()
                            {
                                { "ServiceKey", request.ServiceKey }
                            }));
                        }
                    }
                    else   //check for authorization if required
                    {
                        if (method.IsAuthorizedUserRequired)
                        {
                            bool hasPermission = Permissions.Module.Check(
                                request.Requestor.Account.AccountType,
                                request.Requestor.Account.IdentifierType,
                                request.Requestor.Account.Identifier,
                                string.Format("Method/{0}.{1}", request.ServiceKey, request.MethodKey)
                                );

                            if (!hasPermission)
                            {
                                method = null;
                                LogFault(request, reply, "AuthorizedUserRequiredForMethod", Settings.GetString("FaultMessageMethodAuthorizedUserRequired", new Dictionary <string, string>()
                                {
                                    { "MethodKey", request.MethodKey }
                                }));
                            }
                        }
                        else if (service.IsAuthorizedUserRequired)
                        {
                            bool hasPermission = Permissions.Module.Check(
                                request.Requestor.Account.AccountType,
                                request.Requestor.Account.IdentifierType,
                                request.Requestor.Account.Identifier,
                                string.Format("Service/{0}", request.ServiceKey, request.MethodKey)
                                );

                            if (!hasPermission)
                            {
                                method = null;
                                LogFault(request, reply, "AuthorizedUserRequiredForService", Settings.GetString("FaultMessageServiceAuthorizedUserRequired", new Dictionary <string, string>()
                                {
                                    { "ServiceKey", request.ServiceKey }
                                }));
                            }
                        }
                    }
                }

                //service and method were found and are valid, process request
                if (method != null)
                {
                    //is permanent logging required
                    if (request.Application.IsLogged || service.IsLogged || method.IsLogged)
                    {
                        if (request.Requestor.ClientIPAddress != null)
                        {
                            executionTime = InvokeMethod(method, request, reply, dtprocessed, true);
                        }
                        else
                        {
                            LogFault(request, reply, "UserIpRequired", Settings.GetString("FaultMessageUserIpRequired", new Dictionary <string, string>()
                            {
                                { "ServiceName", service.Name },
                                { "MethodName", method.Name }
                            }));
                        }
                    }
                    else
                    {
                        executionTime = InvokeMethod(method, request, reply, dtprocessed, false);
                    }
                }

                //add application details
                if (request.Application != null && !request.IsProxied)
                {
                    XmlElement app = reply.Response.AddElement(Settings.GetString("NodeNameApplication"));
                    reply.Response.AddElement(app, Settings.GetString("NodeNameApplicationApiKey"), (request.APIKey.Key == null ? Settings.GetString("SymbolNotSpecified") : request.APIKey.Key));
                    reply.Response.AddElement(app, Settings.GetString("NodeNameApplicationName"), (request.Application == null ? string.Empty : request.Application.Name));
                }

                //add service details
                if (service != null)
                {
                    XmlElement xService;
                    xService = reply.Response.AddElement(Settings.GetString("NodeNameService"), request.ServiceKey);
                    xService.SetAttribute(Settings.GetString("NodeAttributeServiceCompiledOn"), service.CompiledOn);
                    xService.SetAttribute(Settings.GetString("NodeAttributeServiceVersion"), service.Version);

                    //add method details
                    if (request.MethodKey != null)
                    {
                        reply.Response.AddElement(Settings.GetString("NodeNameMethod"), request.MethodKey);
                    }
                }

                //add host details
                reply.Response.AddElement(Settings.GetString("NodeNameLegionHost"), string.Format("{0}:{1}", System.Environment.MachineName, System.Diagnostics.Process.GetCurrentProcess().Id));
                reply.Response.AddElement(Settings.GetString("NodeNameProcessedOn"), Settings.FormatDateTime(dtprocessed));

                //add time diagnostics
                reply.Response.AddElement(Settings.GetString("NodeNameElapsedTime"), string.Format("{0} ms", (executionTime.TotalMilliseconds == 0 ? "less than 1" : string.Empty + executionTime.TotalMilliseconds)));
            }
            catch (HandlingError e) {
                LogFault(request, reply, e.GetType().ToString(), e.Message);
            }
            finally {
                //mark the request as complete and clean up the request stack
                request.Complete();
            }

            return(reply);
        }