/// <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); }