Beispiel #1
0
        /// <summary>
        /// Perform the dispatching function of the service
        /// </summary>
        internal bool Dispatch(RestRequestMessage requestMessage, RestResponseMessage responseMessage)
        {
            try
            {
                this.m_traceSource.TraceEvent(TraceEventType.Verbose, 0, "Begin service dispatch of {0} {1} > {2}", requestMessage.Method, requestMessage.Url, this.m_service.Name);

                // Endpoint
                var ep = this.m_service.Endpoints.FirstOrDefault(o => o.Dispatcher.CanDispatch(requestMessage));

                // Find the endpoint
                if (ep == null)
                {
                    throw new FaultException(404, "Resource not Found");
                }

                RestOperationContext.Current.ServiceEndpoint = ep;

                // Apply the policy on the specified context
                foreach (var pol in this.m_servicePolicies)
                {
                    RestOperationContext.Current.AddAppliedPolicy(pol);
                    pol.Apply(requestMessage);
                }

                return(ep.Dispatcher.Dispatch(this, requestMessage, responseMessage));
            }
            catch (Exception e)
            {
                return(this.HandleFault(e, responseMessage));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Handle the provided fault
        /// </summary>
        internal bool HandleFault(Exception e, RestResponseMessage responseMessage)
        {
            var erh = this.m_errorHandlers.FirstOrDefault(o => o.HandleError(e));

            erh?.ProvideFault(e, responseMessage);
            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Provide the actual fault message
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage response)
        {
            if (error is SecurityException)
            {
                response.StatusCode = 403;
            }
            else if (error is FileNotFoundException || error is KeyNotFoundException)
            {
                response.StatusCode = 404;
            }
            else if (error is DuplicateNameException)
            {
                response.StatusCode = 409;
            }
            else
            {
                response.StatusCode = 500;
            }

            var errorResponse = new ErrorResult(error);

            response.Body        = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(errorResponse)));
            response.ContentType = "application/json";
            return(true);
        }
Beispiel #4
0
 /// <summary>
 /// Process the request from the <paramref name="state"/> passed
 /// on the action.
 /// </summary>
 private void DoProcessRequestInternal(Object accept)
 {
     {
         var context = accept as HttpListenerContext;
         try
         {
             RestOperationContext.Current = new RestOperationContext(context);
             var requestMessage = new RestRequestMessage(context.Request);
             using (var responseMessage = new RestResponseMessage(context.Response))
             {
                 this.m_serviceDispatcher.Dispatch(requestMessage, responseMessage);
                 if (requestMessage.Method.ToLowerInvariant() != "head")
                 {
                     responseMessage.FlushResponseStream();
                 }
             }
         }
         catch (Exception e)
         {
             this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, e.ToString());
         }
         finally
         {
             RestOperationContext.Current.Dispose();
         }
     }
 }
Beispiel #5
0
        /// <summary>
        /// Provide the fault
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage response)
        {
            var errCode = WebErrorUtility.ClassifyException(error, true);
            var hdlr    = ApplicationContext.Current.GetService <IAppletManagerService>().Applets.SelectMany(o => o.ErrorAssets).FirstOrDefault(o => o.ErrorCode == errCode);

#if DEBUG
            var ie = error;
            while (ie != null)
            {
                this.m_tracer.TraceError("{0} - ({1}){2} - {3}", error == ie ? "" : "Caused By",
                                         RestOperationContext.Current.EndpointOperation?.Description.InvokeMethod.Name,
                                         ie.GetType().FullName, ie.Message);
                ie = ie.InnerException;
            }
#else
            if (error is TargetInvocationException)
            {
                this.m_tracer.TraceError("{0} - {1} / {2}", RestOperationContext.Current.EndpointOperation.Description.InvokeMethod.Name, error.Message, error.InnerException?.Message);
            }
            else
            {
                this.m_tracer.TraceError("{0} - {1}", RestOperationContext.Current.EndpointOperation.Description.InvokeMethod.Name, error.Message);
            }
#endif

            // Grab the asset handler
            try
            {
                if (hdlr != null)
                {
                    response.Body = new MemoryStream(new byte[0]);
                    RestOperationContext.Current.OutgoingResponse.Redirect(hdlr.Asset);
                }
                else
                {
                    RestOperationContext.Current.OutgoingResponse.StatusCode = errCode;
                    using (var sr = new StreamReader(typeof(AgsWebErrorHandlerServiceBehavior).Assembly.GetManifestResourceStream("SanteDB.DisconnectedClient.Ags.Resources.GenericError.html")))
                    {
                        string errRsp = sr.ReadToEnd().Replace("{status}", response.StatusCode.ToString())
                                        .Replace("{description}", response.StatusDescription)
                                        .Replace("{type}", error.GetType().Name)
                                        .Replace("{message}", error.Message)
                                        .Replace("{details}", error.ToString())
                                        .Replace("{trace}", error.StackTrace);
                        RestOperationContext.Current.OutgoingResponse.ContentType = "text/html";
                        response.Body = new MemoryStream(Encoding.UTF8.GetBytes(errRsp));
                    }
                }

                AuditUtil.AuditNetworkRequestFailure(error, RestOperationContext.Current.IncomingRequest.Url, RestOperationContext.Current.IncomingRequest.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.IncomingRequest.Headers[o]), RestOperationContext.Current.OutgoingResponse.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.OutgoingResponse.Headers[o]));

                return(true);
            }
            catch (Exception e)
            {
                Tracer.GetTracer(typeof(AgsWebErrorHandlerServiceBehavior)).TraceError("Could not provide fault: {0}", e.ToString());
                throw;
            }
        }
        /// <summary>
        /// Before sending the response
        /// </summary>
        public void BeforeSendResponse(RestResponseMessage response)
        {
            var processingTime = DateTime.Now.Subtract(httpCorrelation.Value);

            this.m_traceSource.TraceEvent(EventLevel.Verbose, "HTTP RSP {0} : {1} ({2} ms)",
                                          httpCorrelation.Key,
                                          response.StatusCode,
                                          processingTime.TotalMilliseconds);
        }
Beispiel #7
0
        /// <summary>
        /// Before sending a response
        /// </summary>
        public void BeforeSendResponse(RestResponseMessage response)
        {
            //response.Headers.Add("Content-Security-Policy", $"script-src-elem 'nonce-{this.Nonce}'; script-src 'self'");
            response.Headers.Add("Content-Security-Policy", $"script-src-elem 'self' 'nonce-{this.Nonce}' 'strict-dynamic'; script-src 'self' 'nonce-{this.Nonce}'");
            response.Headers.Add("X-XSS-Protection", "1; mode=block");
            response.Headers.Add("X-Frame-Options", "deny");

            response.Headers.Add("Feature-Policy", "autoplay 'none'; accelerometer 'none'; geolocation 'none'; payment 'none'");

            response.Headers.Add("X-Content-Type-Options", "nosniff");
        }
Beispiel #8
0
        /// <summary>
        /// Rest http request is made by this method with parameters supplied
        /// </summary>
        /// <param name="restRequestParameter"></param>
        /// <returns></returns>
        public async Task <HttpResponseMessage> SendRequestAsync(RestRequestParameter restRequestParameter)
        {
            HttpResponseMessage response;

            Uri url = restRequestParameter.GetRequestUri();

            if (restRequestParameter.IgnoreCertificateErrors)
            {
                ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { return(true); };
            }

            using (HttpClient httpClient = CreateHttpClient(restRequestParameter.RequestTimeOut, restRequestParameter.ClientCertificates))
            {
                HttpRequestMessage httpRequestMessage = null;
                try
                {
                    httpRequestMessage = new HttpRequestMessage(restRequestParameter.HttpMethod, url)
                    {
                        Content = restRequestParameter.RequestContent
                    };

                    if (restRequestParameter.HeaderParameters != null)
                    {
                        foreach (var headerDefinition in restRequestParameter.HeaderParameters.Keys)
                        {
                            httpRequestMessage.Headers.Add(headerDefinition, restRequestParameter.HeaderParameters[headerDefinition]);
                        }
                    }

                    response = await httpClient.SendAsync(httpRequestMessage);
                }
                catch (Exception ex)
                {
                    Exception sourceException = ex;
                    if (ex.InnerException != null)
                    {
                        sourceException = ex.InnerException;
                    }

                    RestResponseMessage restReponseMessage = new RestResponseMessage(HttpStatusCode.BadRequest, sourceException)
                    {
                        RequestMessage = httpRequestMessage
                    };

                    response = restReponseMessage;
                }
            }
            return(response);
        }
        /// <summary>
        /// Provide a fault
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage response)
        {
            this.m_tracer.TraceEvent(EventLevel.Error, "Error on WCF FHIR Pipeline: {0}", error);

            RestOperationContext.Current.OutgoingResponse.StatusCode = ClassifyErrorCode(error);
            if (RestOperationContext.Current.OutgoingResponse.StatusCode == 401)
            {
                // Get to the root of the error
                while (error.InnerException != null)
                {
                    error = error.InnerException;
                }

                if (error is PolicyViolationException pve)
                {
                    var method = RestOperationContext.Current.AppliedPolicies.Any(o => o.GetType().Name.Contains("Basic")) ? "Basic" : "Bearer";
                    response.AddAuthenticateHeader(method, RestOperationContext.Current.IncomingRequest.Url.Host, "insufficient_scope", pve.PolicyId, error.Message);
                }
                else if (error is SecurityTokenException ste)
                {
                    response.AddAuthenticateHeader("Bearer", RestOperationContext.Current.IncomingRequest.Url.Host, "token_error", description: ste.Message);
                }
                else if (error is SecuritySessionException ses)
                {
                    switch (ses.Type)
                    {
                    case SessionExceptionType.Expired:
                    case SessionExceptionType.NotYetValid:
                    case SessionExceptionType.NotEstablished:
                        response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                        response.AddAuthenticateHeader("Bearer", RestOperationContext.Current.IncomingRequest.Url.Host, "unauthorized", PermissionPolicyIdentifiers.Login, ses.Message);
                        break;

                    default:
                        response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
                        break;
                    }
                }
            }

            var errorResult = DataTypeConverter.CreateErrorResult(error);

            // Return error in XML only at this point
            new FhirMessageDispatchFormatter().SerializeResponse(response, null, errorResult);
            return(true);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private async Task <Exception> ParseResponseErrorMessageContent(HttpResponseMessage response)
        {
            Exception           exceptionResult;
            RestResponseMessage responseMessage = response as RestResponseMessage;

            if (responseMessage != null)
            {
                exceptionResult = responseMessage.Exception;
            }
            else
            {
                string errorMessage = await response.Content.ReadAsStringAsync();

                exceptionResult = new RestServiceException((int)response.StatusCode, errorMessage);
            }

            return(exceptionResult);
        }
Beispiel #11
0
        /// <summary>
        /// Before sending the response
        /// </summary>
        public void BeforeSendResponse(RestResponseMessage response)
        {
            var ext = RestOperationContext.Current.IncomingRequest.Url.AbsolutePath;

            if (ext.Contains("."))
            {
                ext = ext.Substring(ext.LastIndexOf("."));
                if (this.cacheExtensions.Contains(ext))
                {
                    RestOperationContext.Current.OutgoingResponse.AddHeader("Cache-Control", "public, max-age=28800");
                    RestOperationContext.Current.OutgoingResponse.AddHeader("Expires", DateTime.UtcNow.AddHours(1).ToString("ddd, dd MMM yyyy HH:mm:ss 'GMT'"));
                }
                else
                {
                    RestOperationContext.Current.OutgoingResponse.AddHeader("Cache-Control", "no-cache");
                }
            }
        }
        /// <summary>
        /// Provide a fault
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage response)
        {
            this.m_tracer.TraceEvent(EventLevel.Error, "Error on OAUTH Pipeline: {0}", error);

            // Error
            OAuthError err = new OAuthError()
            {
                Error            = OAuthErrorType.invalid_request,
                ErrorDescription = error.Message
            };

            JsonSerializer serializer = new JsonSerializer();

            response.ContentType = "application/json";
            using (var stw = new StringWriter())
            {
                serializer.Serialize(stw, err);
                response.Body = new MemoryStream(Encoding.UTF8.GetBytes(stw.ToString()));
            }

            return(true);
        }
        /// <summary>
        /// Before send response
        /// </summary>
        public void BeforeSendResponse(RestResponseMessage response)
        {
            // TODO: Add a configuration option to disable this
            var resourcePath = RestOperationContext.Current.IncomingRequest.Url.AbsolutePath.Substring(RestOperationContext.Current.ServiceEndpoint.Description.ListenUri.AbsolutePath.Length);
            var settings     = this.m_settings.Resource.FirstOrDefault(o => o.Name == "*" || o.Name == resourcePath);

            if (settings != null)
            {
                Dictionary <String, String> requiredHeaders = new Dictionary <string, string>()
                {
                    { "Access-Control-Allow-Origin", settings.Domain },
                    { "Access-Control-Allow-Methods", String.Join(",", settings.Verbs) },
                    { "Access-Control-Allow-Headers", String.Join(",", settings.Headers) }
                };
                foreach (var kv in requiredHeaders)
                {
                    if (!RestOperationContext.Current.OutgoingResponse.Headers.AllKeys.Contains(kv.Key))
                    {
                        RestOperationContext.Current.OutgoingResponse.Headers.Add(kv.Key, kv.Value);
                    }
                }
            }
        }
        /// <summary>
        /// Serialize the reply
        /// </summary>
        public void SerializeResponse(RestResponseMessage responseMessage, object[] parameters, object result)
        {
            try
            {
                // Outbound control
                var    httpRequest = RestOperationContext.Current.IncomingRequest;
                string accepts     = httpRequest.Headers["Accept"],
                       contentType = httpRequest.Headers["Content-Type"],
                       formatParm  = httpRequest.QueryString["_format"];

                // Result is serializable
                if (result?.GetType().GetCustomAttribute <XmlTypeAttribute>() != null ||
                    result?.GetType().GetCustomAttribute <JsonObjectAttribute>() != null)
                {
                    XmlSerializer xsz = XmlModelSerializerFactory.Current.CreateSerializer(result.GetType());
                    MemoryStream  ms  = new MemoryStream();
                    xsz.Serialize(ms, result);
                    contentType = "application/fhir+xml";
                    ms.Seek(0, SeekOrigin.Begin);
                    // The request was in JSON or the accept is JSON
                    if (accepts?.StartsWith("application/fhir+json") == true ||
                        contentType?.StartsWith("application/fhir+json") == true ||
                        formatParm?.Contains("application/fhir+json") == true)
                    {
                        // Parse XML object
                        Object fhirObject = null;
                        using (StreamReader sr = new StreamReader(ms))
                        {
                            String fhirContent = sr.ReadToEnd();
                            var    parser      = new FhirXmlParser();
                            parser.Settings.AllowUnrecognizedEnums      = true;
                            parser.Settings.AcceptUnknownMembers        = true;
                            parser.Settings.DisallowXsiAttributesOnRoot = false;
                            fhirObject = parser.Parse <Resource>(fhirContent);
                        }

                        // Now we serialize to JSON
                        byte[] body = new FhirJsonSerializer().SerializeToBytes(fhirObject as Hl7.Fhir.Model.Resource);
                        ms.Dispose();
                        ms = new MemoryStream(body);
                        // Prepare reply for the WCF pipeline
                        contentType = "application/fhir+json";
                    }
                    responseMessage.Body = ms;
                }
                else if (result is XmlSchema)
                {
                    MemoryStream ms = new MemoryStream();
                    (result as XmlSchema).Write(ms);
                    ms.Seek(0, SeekOrigin.Begin);
                    contentType          = "text/xml";
                    responseMessage.Body = ms;
                }
                else if (result is Stream) // TODO: This is messy, clean it up
                {
                    responseMessage.Body = result as Stream;
                }


                RestOperationContext.Current.OutgoingResponse.ContentType = contentType;
                RestOperationContext.Current.OutgoingResponse.AppendHeader("X-PoweredBy", String.Format("{0} v{1} ({2})", Assembly.GetEntryAssembly().GetName().Name, Assembly.GetEntryAssembly().GetName().Version, Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion));
                RestOperationContext.Current.OutgoingResponse.AppendHeader("X-GeneratedOn", DateTime.Now.ToString("o"));
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
                throw;
            }
        }
        /// <summary>
        /// Provide fault
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage faultMessage)
        {
            var uriMatched = RestOperationContext.Current.IncomingRequest.Url;

            while (error.InnerException != null)
            {
                error = error.InnerException;
            }

            var fault      = new RestServiceFault(error);
            var authScheme = RestOperationContext.Current.AppliedPolicies.OfType <BasicAuthorizationAccessBehavior>().Any() ? "Basic" : "Bearer";
            var authRealm  = RestOperationContext.Current.IncomingRequest.Url.Host;

            // Formulate appropriate response
            if (error is DomainStateException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.ServiceUnavailable;
            }
            else if (error is ObjectLockedException lockException)
            {
                faultMessage.StatusCode = 423;
                fault.Data.Add(lockException.LockedUser);
            }
            else if (error is PolicyViolationException)
            {
                var pve = error as PolicyViolationException;
                if (pve.PolicyDecision == PolicyGrantType.Elevate)
                {
                    // Ask the user to elevate themselves
                    faultMessage.StatusCode = 401;
                    faultMessage.AddAuthenticateHeader(authScheme, authRealm, "insufficient_scope", pve.PolicyId, error.Message);
                }
                else
                {
                    faultMessage.StatusCode = 403;
                }
            }
            else if (error is SecurityException)
            {
                faultMessage.StatusCode = (int)HttpStatusCode.Forbidden;
            }
            else if (error is SecurityTokenException)
            {
                // TODO: Audit this
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                var authHeader = $"Bearer realm=\"{RestOperationContext.Current.IncomingRequest.Url.Host}\" error=\"invalid_token\" error_description=\"{error.Message}\"";
                faultMessage.AddAuthenticateHeader(authScheme, authRealm, error: "invalid_token", description: error.Message);
            }
            else if (error is LimitExceededException)
            {
                faultMessage.StatusCode        = (int)(HttpStatusCode)429;
                faultMessage.StatusDescription = "Too Many Requests";
                faultMessage.Headers.Add("Retry-After", "1200");
            }
            else if (error is AuthenticationException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                faultMessage.AddAuthenticateHeader(authScheme, authRealm, "invalid_token", description: error.Message);
            }
            else if (error is UnauthorizedAccessException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            }
            else if (error is SecuritySessionException ses)
            {
                switch (ses.Type)
                {
                case SessionExceptionType.Expired:
                case SessionExceptionType.NotYetValid:
                case SessionExceptionType.NotEstablished:
                    faultMessage.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                    faultMessage.AddAuthenticateHeader(authScheme, authRealm, error: "unauthorized");
                    break;

                default:
                    faultMessage.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
                    break;
                }
            }
            else if (error is FaultException)
            {
                faultMessage.StatusCode = (int)(error as FaultException).StatusCode;
            }
            else if (error is Newtonsoft.Json.JsonException ||
                     error is System.Xml.XmlException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
            }
            else if (error is DuplicateKeyException || error is DuplicateNameException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.Conflict;
            }
            else if (error is FileNotFoundException || error is KeyNotFoundException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
            }
            else if (error is DomainStateException)
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.ServiceUnavailable;
            }
            else if (error is DetectedIssueException)
            {
                faultMessage.StatusCode = (int)(System.Net.HttpStatusCode) 422;
            }
            else if (error is NotImplementedException)
            {
                faultMessage.StatusCode = (int)HttpStatusCode.NotImplemented;
            }
            else if (error is NotSupportedException)
            {
                faultMessage.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
            }
            else if (error is PatchException)
            {
                faultMessage.StatusCode = (int)HttpStatusCode.Conflict;
            }
            else
            {
                faultMessage.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
            }

            switch (faultMessage.StatusCode)
            {
            case 409:
            case 429:
            case 503:
                this.m_traceSource.TraceInfo("Issue on REST pipeline: {0}", error);
                break;

            case 401:
            case 403:
            case 501:
            case 405:
                this.m_traceSource.TraceWarning("Warning on REST pipeline: {0}", error);
                break;

            default:
                this.m_traceSource.TraceError("Error on REST pipeline: {0}", error);
                break;
            }

            RestMessageDispatchFormatter.CreateFormatter(RestOperationContext.Current.ServiceEndpoint.Description.Contract.Type).SerializeResponse(faultMessage, null, fault);
            AuditUtil.AuditNetworkRequestFailure(error, uriMatched, RestOperationContext.Current.IncomingRequest.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.IncomingRequest.Headers[o]), RestOperationContext.Current.OutgoingResponse.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.OutgoingResponse.Headers[o]));
            return(true);
        }
        /// <summary>  Constructor for a new instance of the Delete_Verify_WebContentViewer class  </summary>
        /// <param name="RequestSpecificValues">  All the necessary, non-global data specific to the current request  </param>
        /// <param name="StaticPage"> Static page info for this request </param>
        public Delete_Verify_WebContentViewer(RequestCache RequestSpecificValues, HTML_Based_Content StaticPage)
            : base(RequestSpecificValues, StaticPage)
        {
            // Pull the web content page
            if (RequestSpecificValues.Current_Mode.WebContentID.HasValue)
            {
                webContent = SobekEngineClient.WebContent.Get_HTML_Based_Content(RequestSpecificValues.Current_Mode.WebContentID.Value, true, RequestSpecificValues.Tracer);
            }

            // This should never occur, but just a double check
            if ((webContent == null) || (!webContent.WebContentID.HasValue))
            {
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                UrlWriterHelper.Redirect(RequestSpecificValues.Current_Mode);
                return;
            }

            // Ensure there IS a logged on user
            RequestSpecificValues.Tracer.Add_Trace("Delete_Item_MySobekViewer.Delete_Verify_WebContentViewer", "Validate user");
            if ((RequestSpecificValues.Current_User == null) || (!RequestSpecificValues.Current_User.LoggedOn))
            {
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                UrlWriterHelper.Redirect(RequestSpecificValues.Current_Mode);
                return;
            }

            // If the user was logged on, but did not have permissions, show an error message
            canDelete = true;
            deleted   = false;
            if (!webContent.Can_Delete(RequestSpecificValues.Current_User))
            {
                errorMessage = "ERROR: You do not have permission to delete this page";
                canDelete    = false;
            }
            else if (HttpContext.Current.Request.RequestType == "POST")
            {
                string save_value = HttpContext.Current.Request.Form["admin_delete_item"];

                // Better say "DELETE", or just send back to the item
                if ((save_value != null) && (String.Compare(save_value, "DELETE", StringComparison.OrdinalIgnoreCase) == 0))
                {
                    string entered_value = HttpContext.Current.Request.Form["admin_delete_confirm"];
                    if ((entered_value == null) || (entered_value.ToUpper() != "DELETE"))
                    {
                        errorMessage = "ERROR: To verify this deletion, type DELETE into the text box and press CONFIRM";
                    }
                    else
                    {
                        string deleteReason = "Requested via web application";


                        RestResponseMessage message = SobekEngineClient.WebContent.Delete_HTML_Based_Content(webContent.WebContentID.Value, RequestSpecificValues.Current_User.Full_Name, deleteReason, RequestSpecificValues.Tracer);

                        errorMessage = message.Message;
                        if ((message.ErrorTypeEnum != ErrorRestTypeEnum.Successful) && (String.IsNullOrEmpty(errorMessage)))
                        {
                            errorMessage = "Error encountered on SobekCM engine.";
                        }
                        else
                        {
                            errorMessage = "Successfully deleted this web content page.";

                            // Clear cached data here on the client
                            CachedDataManager.WebContent.Clear_All_Web_Content_Lists();
                            CachedDataManager.WebContent.Clear_All_Web_Content_Pages();
                            CachedDataManager.WebContent.Clear_Page_Details();
                            UI_ApplicationCache_Gateway.WebContent_Hierarchy_Clear();

                            deleted = true;
                        }
                    }
                }
            }
        }
Beispiel #17
0
 /// <summary>
 /// Implemented below
 /// </summary>
 public abstract void SerializeResponse(RestResponseMessage response, object[] parameters, object result);
Beispiel #18
0
        /// <summary>
        /// Serialize the reply
        /// </summary>
        public override void SerializeResponse(RestResponseMessage response, object[] parameters, object result)
        {
            try
            {
                // Outbound control
                var    httpRequest = RestOperationContext.Current.IncomingRequest;
                string accepts     = httpRequest.Headers["Accept"]?.ToLower(),
                       contentType = httpRequest.Headers["Content-Type"]?.ToLower();

                // The request was in JSON or the accept is JSON
                if (result is Stream) // TODO: This is messy, clean it up
                {
                    contentType   = "application/octet-stream";
                    response.Body = result as Stream;
                }
                else if (accepts?.StartsWith("application/json+sdb-viewmodel") == true &&
                         typeof(IdentifiedData).IsAssignableFrom(result?.GetType()))
                {
                    var viewModel = httpRequest.Headers["X-SanteDB-ViewModel"] ?? httpRequest.QueryString["_viewModel"];

                    // Create the view model serializer
                    using (AuthenticationContextExtensions.TryEnterDeviceContext())
                    {
                        var viewModelSerializer = new JsonViewModelSerializer();
                        viewModelSerializer.LoadSerializerAssembly(typeof(ActExtensionViewModelSerializer).Assembly);

                        if (!String.IsNullOrEmpty(viewModel))
                        {
                            var viewModelDescription = ApplicationContext.Current.GetService <IAppletManagerService>()?.Applets.GetViewModelDescription(viewModel);
                            viewModelSerializer.ViewModel = viewModelDescription;
                        }
                        else
                        {
                            viewModelSerializer.ViewModel = m_defaultViewModel;
                        }

                        using (var tms = new MemoryStream())
                            using (StreamWriter sw = new StreamWriter(tms, Encoding.UTF8))
                                using (JsonWriter jsw = new JsonTextWriter(sw))
                                {
                                    viewModelSerializer.Serialize(jsw, result as IdentifiedData);
                                    jsw.Flush();
                                    sw.Flush();
                                    response.Body = new MemoryStream(tms.ToArray());
                                }
                    }
                    contentType = "application/json+sdb-viewModel";
                }
                // The request was in XML and/or the accept is JSON
                else if ((accepts?.StartsWith("application/xml") == true ||
                          contentType?.StartsWith("application/xml") == true) &&
                         result?.GetType().GetCustomAttribute <XmlTypeAttribute>() != null)
                {
                    XmlSerializer xsz = XmlModelSerializerFactory.Current.CreateSerializer(result.GetType());
                    MemoryStream  ms  = new MemoryStream();
                    xsz.Serialize(ms, result);
                    contentType = "application/xml";
                    ms.Seek(0, SeekOrigin.Begin);
                    response.Body = ms;
                }
                else if (result is XmlSchema)
                {
                    MemoryStream ms = new MemoryStream();
                    (result as XmlSchema).Write(ms);
                    ms.Seek(0, SeekOrigin.Begin);
                    contentType   = "text/xml";
                    response.Body = ms;
                }
                else if (result != null)
                {
                    // Prepare the serializer
                    JsonSerializer jsz = new JsonSerializer();
                    jsz.Converters.Add(new StringEnumConverter());

                    // Write json data
                    using (MemoryStream ms = new MemoryStream())
                        using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
                            using (JsonWriter jsw = new JsonTextWriter(sw))
                            {
                                jsz.DateFormatHandling    = DateFormatHandling.IsoDateFormat;
                                jsz.NullValueHandling     = NullValueHandling.Ignore;
                                jsz.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                                jsz.TypeNameHandling      = TypeNameHandling.Auto;
                                jsz.Converters.Add(new StringEnumConverter());
                                jsz.Serialize(jsw, result);
                                jsw.Flush();
                                sw.Flush();
                                response.Body = new MemoryStream(ms.ToArray());
                            }

                    // Prepare reply for the WCF pipeline
                    contentType = "application/json";
                }
                else if (response.StatusCode == 0)
                {
                    response.StatusCode = 204; // no content
                }
                RestOperationContext.Current.OutgoingResponse.ContentType = RestOperationContext.Current.OutgoingResponse.ContentType ?? contentType;
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceError("Error Serializing Dispatch Reply: {0}", e.ToString());
                new AgsErrorHandlerServiceBehavior().ProvideFault(e, response);
            }
        }
Beispiel #19
0
        /// <summary>
        /// Provide the fault to the pipeline
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage response)
        {
            response.Body = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(error.ToString()));

            var cause = error;

            while (cause.InnerException != null)
            {
                cause = cause.InnerException;
            }

            if (cause is FileNotFoundException || cause is KeyNotFoundException)
            {
                response.StatusCode = 404;
            }
            else if (cause is InvalidOperationException)
            {
                response.StatusCode = 500;
            }
            else if (cause is XmlException || cause is JsonException)
            {
                response.StatusCode = 400;
            }
            else if (cause is SecurityException || cause is UnauthorizedAccessException)
            {
                response.AddAuthenticateHeader("bearer", RestOperationContext.Current.IncomingRequest.Headers["Host"]);
                response.StatusCode = 401;
            }
            else if (cause is NotSupportedException)
            {
                response.StatusCode = 405;
            }
            else if (cause is NotImplementedException)
            {
                response.StatusCode = 501;
            }
            else if (cause is FaultException)
            {
                response.StatusCode = (cause as FaultException).StatusCode;
                if (cause.GetType() != typeof(FaultException)) // Special classification
                {
                    var errorData = error.GetType().GetRuntimeProperty("Body").GetValue(cause);
                    new DefaultDispatchFormatter().SerializeResponse(response, null, errorData);
                    return(true);
                }
            }
            else
            {
                response.StatusCode = 500;
            }

            // Load the exception screen
            using (var sr = new StreamReader(typeof(DefaultErrorHandler).Assembly.GetManifestResourceStream("RestSrvr.Resources.ServiceError.html")))
            {
                response.ContentType = "text/html";
                var errRet = sr.ReadToEnd().Replace("{status}", response.StatusCode.ToString())
                             .Replace("{description}", response.StatusDescription)
                             .Replace("{type}", error.GetType().Name)
                             .Replace("{message}", error.Message)
                             .Replace("{details}", error.ToString())
                             .Replace("{trace}", error.StackTrace);
                response.Body        = new MemoryStream(Encoding.UTF8.GetBytes(errRet));
                response.ContentType = "text/html";
            }
            return(true);
        }
        /// <summary>
        /// Provide the fault
        /// </summary>
        /// <param name="error"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        public bool ProvideFault(Exception error, RestResponseMessage faultMessage)
        {
            try
            {
#if DEBUG
                this.m_tracer.TraceWarning("Error on pipeline: {0}", error);
#else
                if (error is TargetInvocationException tie)
                {
                    this.m_tracer.TraceWarning("{0} - {1} / {2}", RestOperationContext.Current?.EndpointOperation?.Description?.InvokeMethod?.Name, error.Message, error.InnerException?.Message);
                }
                else
                {
                    this.m_tracer.TraceWarning("{0} - {1}", RestOperationContext.Current?.EndpointOperation?.Description?.InvokeMethod?.Name, error.Message);
                }
#endif

                if (faultMessage == null)
                {
                    if (RestOperationContext.Current.OutgoingResponse == null)
                    {
                        this.m_tracer.TraceWarning("Client hangup");
                        return(false);
                    }
                    this.m_tracer.TraceWarning("For some reason the fault message is null - ");
                    faultMessage = new RestResponseMessage(RestOperationContext.Current.OutgoingResponse);
                }
                var ie = error;
                while (ie != null)
                {
                    this.m_tracer.TraceWarning("{0} - ({1}){2} - {3}", error == ie ? "" : "Caused By",
                                               RestOperationContext.Current.EndpointOperation?.Description.InvokeMethod.Name,
                                               ie?.GetType().FullName, ie.Message);

                    // TODO: Do we need this or can we just capture the innermost exception as the cause?
                    if (ie is RestClientException <RestServiceFault> || ie is SecurityException || ie is DetectedIssueException ||
                        ie is FileNotFoundException || ie is KeyNotFoundException)
                    {
                        error = ie;
                    }
                    ie = ie.InnerException;
                }
                faultMessage.StatusCode = WebErrorUtility.ClassifyException(error);

                object fault = (error as RestClientException <RestServiceFault>)?.Result ?? new RestServiceFault(error);

                if (error is FaultException && error?.GetType() != typeof(FaultException)) // Special classification
                {
                    fault = error?.GetType().GetRuntimeProperty("Body").GetValue(error);
                }

                var formatter = RestMessageDispatchFormatter.CreateFormatter(RestOperationContext.Current.ServiceEndpoint.Description.Contract.Type);
                if (formatter != null)
                {
                    formatter.SerializeResponse(faultMessage, null, fault);
                }
                else
                {
                    RestOperationContext.Current.OutgoingResponse.OutputStream.Write(System.Text.Encoding.UTF8.GetBytes(error.Message), 0, System.Text.Encoding.UTF8.GetByteCount(error.Message));
                }

                try
                {
                    if (ApplicationServiceContext.Current.GetService <IOperatingSystemInfoService>()?.OperatingSystem != OperatingSystemID.Android)
                    {
                        AuditUtil.AuditNetworkRequestFailure(error, RestOperationContext.Current.IncomingRequest.Url, RestOperationContext.Current.IncomingRequest.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.IncomingRequest.Headers[o]), RestOperationContext.Current.OutgoingResponse.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.OutgoingResponse.Headers[o]));
                    }
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Could not send network request failure - {0}", e);
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error providing fault: {0}", e);
            }
            return(true);
        }
Beispiel #21
0
        /// <summary>
        /// Dispatch the message
        /// </summary>
        internal bool Dispatch(ServiceDispatcher serviceDispatcher, RestRequestMessage requestMessage, RestResponseMessage responseMessage)
        {
            try
            {
                this.m_traceSource.TraceEvent(TraceEventType.Verbose, 0, "Begin operation dispatch of {0} {1} to {2}", requestMessage.Method, requestMessage.Url, this.m_endpointOperation.Description.InvokeMethod);

                foreach (var pol in this.m_operationPolicies)
                {
                    pol.Apply(this.m_endpointOperation, requestMessage);
                }

                var invoke     = this.m_endpointOperation.Description.InvokeMethod;
                var parameters = new object[invoke.GetParameters().Length];

                // By default parameters are passed by name
                var parmMatch = this.m_dispatchRegex.Match(requestMessage.OperationPath);
                for (int i = 0; i < this.m_regexGroupNames.Length; i++)
                {
                    var    pindex = Array.FindIndex(invoke.GetParameters(), o => $"{{{o.Name}}}" == this.m_regexGroupNames[i]);
                    var    sparm  = invoke.GetParameters()[pindex];
                    object sval   = parmMatch.Groups[i + 1].Value;
                    if (sparm.ParameterType == typeof(int))
                    {
                        sval = Int32.Parse(sval.ToString());
                    }
                    else if (sparm.ParameterType == typeof(Guid))
                    {
                        sval = Guid.Parse(sval.ToString());
                    }

                    parameters[pindex] = sval;
                }

                this.DispatchFormatter.DeserializeRequest(this.m_endpointOperation, requestMessage, parameters);

                this.m_traceSource.TraceData(TraceEventType.Verbose, 0, parameters);

                // Validate parameters
                if (!Enumerable.Range(0, invoke.GetParameters().Length).All(o => parameters[o] == null || invoke.GetParameters()[o].ParameterType.IsAssignableFrom(parameters[o]?.GetType())))
                {
                    throw new FaultException(400, "Bad Request");
                }

                // Gather instance
                object instance = serviceDispatcher.Service.Instance;
                if (serviceDispatcher.Service.InstanceMode == Attributes.ServiceInstanceMode.PerCall)
                {
                    instance = Activator.CreateInstance(serviceDispatcher.Service.BehaviorType);
                }

                object result = invoke.Invoke(instance, parameters);

                // Does the invoke override content-type?
                var format = invoke.ReturnParameter.GetCustomAttribute <MessageFormatAttribute>()?.MessageFormat;
                if (format.HasValue)
                {
                    responseMessage.Format = format.Value;
                }

                if (result == null && responseMessage.StatusCode == 0)
                {
                    responseMessage.StatusCode = 204;
                }
                else
                {
                    this.DispatchFormatter.SerializeResponse(responseMessage, parameters, result);
                }

                parameters = null;

                return(true);
            }
            catch (TargetInvocationException e)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, 0, e.ToString());
                return(serviceDispatcher.HandleFault(e.InnerException, responseMessage));
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, e.ToString());
                return(serviceDispatcher.HandleFault(e, responseMessage));
            }
        }
        /// <summary>
        /// Before sending the response
        /// </summary>
        public void BeforeSendResponse(RestResponseMessage response)
        {
            try
            {
                string encodings         = RestOperationContext.Current.IncomingRequest.Headers.Get("Accept-Encoding");
                string compressionScheme = String.Empty;

                if (!string.IsNullOrEmpty(encodings))
                {
                    encodings = encodings.ToLowerInvariant();

                    if (encodings.Contains("lzma"))
                    {
                        compressionScheme = "lzma";
                    }
                    else if (encodings.Contains("bzip2"))
                    {
                        compressionScheme = "bzip2";
                    }
                    else if (encodings.Contains("gzip"))
                    {
                        compressionScheme = "gzip";
                    }
                    else if (encodings.Contains("deflate"))
                    {
                        compressionScheme = "deflate";
                    }
                    else
                    {
                        response.Headers.Add("X-CompressResponseStream", "no-known-accept");
                    }
                }

                // No reply = no compress :)
                if (response.Body == null)
                {
                    return;
                }

                // Finally compress
                // Compress
                if (!String.IsNullOrEmpty(compressionScheme))
                {
                    try
                    {
                        response.Headers.Add("Content-Encoding", compressionScheme);
                        response.Headers.Add("X-CompressResponseStream", compressionScheme);

                        // Read binary contents of the message
                        var memoryStream = new MemoryStream();
                        using (var compressor = CompressionUtil.GetCompressionScheme(compressionScheme).CreateCompressionStream(memoryStream))
                            response.Body.CopyTo(compressor);
                        response.Body.Dispose();
                        memoryStream.Seek(0, SeekOrigin.Begin);
                        response.Body = memoryStream;
                    }
                    catch (Exception e)
                    {
                        this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
                    }
                }
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
            }
        }
Beispiel #23
0
        /// <summary> Constructor for a new instance of the Aggregations_Mgmt_AdminViewer class </summary>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        /// <remarks> Postback from handling an edit or new aggregation is handled here in the constructor </remarks>
        public Aggregations_Mgmt_AdminViewer(RequestCache RequestSpecificValues) : base(RequestSpecificValues)
        {
            RequestSpecificValues.Tracer.Add_Trace("Aggregations_Mgmt_AdminViewer.Constructor", String.Empty);

            // Set some defaults
            actionMessage          = String.Empty;
            enteredCode            = String.Empty;
            enteredParent          = String.Empty;
            enteredType            = String.Empty;
            enteredShortname       = String.Empty;
            enteredName            = String.Empty;
            enteredDescription     = String.Empty;
            enteredThematicHeading = String.Empty;
            enteredIsActive        = true;
            enteredIsHidden        = false;
            addedNewCollection     = false;

            // If the user cannot edit this, go back
            if ((RequestSpecificValues.Current_User == null) || ((!RequestSpecificValues.Current_User.Is_System_Admin) && (!RequestSpecificValues.Current_User.Is_Portal_Admin)))
            {
                RequestSpecificValues.Current_Mode.Mode          = Display_Mode_Enum.My_Sobek;
                RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                UrlWriterHelper.Redirect(RequestSpecificValues.Current_Mode);
                return;
            }

            // If this is a postback, handle any events first
            if (RequestSpecificValues.Current_Mode.isPostBack)
            {
                try
                {
                    // Pull the standard values
                    NameValueCollection form = HttpContext.Current.Request.Form;

                    string save_value           = form["admin_aggr_tosave"].ToUpper().Trim();
                    string new_aggregation_code = String.Empty;
                    if (form["admin_aggr_code"] != null)
                    {
                        new_aggregation_code = form["admin_aggr_code"].ToUpper().Trim();
                    }

                    // Check for reset request as well
                    string reset_aggregation_code = String.Empty;
                    if (form["admin_aggr_reset"] != null)
                    {
                        reset_aggregation_code = form["admin_aggr_reset"].ToLower().Trim();
                    }

                    string delete_aggregation_code = String.Empty;
                    if (form["admin_aggr_delete"] != null)
                    {
                        delete_aggregation_code = form["admin_aggr_delete"].ToLower().Trim();
                    }

                    // Was this to delete the aggregation?
                    if (delete_aggregation_code.Length > 0)
                    {
                        string delete_error;
                        int    errorCode = SobekCM_Database.Delete_Item_Aggregation(delete_aggregation_code, RequestSpecificValues.Current_User.Is_System_Admin, RequestSpecificValues.Current_User.Full_Name, RequestSpecificValues.Tracer, out delete_error);
                        if (errorCode <= 0)
                        {
                            string delete_folder = UI_ApplicationCache_Gateway.Settings.Servers.Base_Design_Location + "aggregations\\" + delete_aggregation_code;
                            if (!SobekCM_File_Utilities.Delete_Folders_Recursively(delete_folder))
                            {
                                actionMessage = "Deleted '" + delete_aggregation_code.ToUpper() + "' aggregation<br /><br />Unable to remove aggregation directory<br /><br />Some of the files may be in use";
                            }
                            else
                            {
                                actionMessage = "Deleted '" + delete_aggregation_code.ToUpper() + "' aggregation";
                            }
                        }
                        else
                        {
                            actionMessage = delete_error;
                        }

                        CachedDataManager.Aggregations.Clear();

                        // Reload the list of all codes, to include this new one and the new hierarchy
                        lock (UI_ApplicationCache_Gateway.Aggregations)
                        {
                            Engine_Database.Populate_Code_Manager(UI_ApplicationCache_Gateway.Aggregations, RequestSpecificValues.Tracer);
                        }
                    }


                    // If there is a reset request here, purge the aggregation from the cache
                    if (reset_aggregation_code.Length > 0)
                    {
                        CachedDataManager.Aggregations.Remove_Item_Aggregation(reset_aggregation_code, RequestSpecificValues.Tracer);
                    }

                    // If there was a save value continue to pull the rest of the data
                    if (save_value.Length > 0)
                    {
                        bool is_active = false;
                        bool is_hidden = true;


                        // Was this to save a new aggregation (from the main page) or edit an existing (from the popup form)?
                        if (save_value == new_aggregation_code)
                        {
                            addedNewCollection = true;

                            // Pull the values from the submitted form
                            string new_type             = form["admin_aggr_type"];
                            string new_parent           = form["admin_aggr_parent"].Trim();
                            string new_name             = form["admin_aggr_name"].Trim();
                            string new_shortname        = form["admin_aggr_shortname"].Trim();
                            string new_description      = form["admin_aggr_desc"].Trim();
                            string new_link             = form["admin_aggr_link"].Trim();
                            string new_thematic_heading = form["admin_aggr_heading"].Trim();

                            object temp_object = form["admin_aggr_isactive"];
                            if (temp_object != null)
                            {
                                is_active = true;
                            }

                            temp_object = form["admin_aggr_ishidden"];
                            if (temp_object != null)
                            {
                                is_hidden = false;
                            }

                            // Convert to the integer id for the parent and begin to do checking
                            List <string> errors = new List <string>();
                            if (String.IsNullOrEmpty(new_parent))
                            {
                                errors.Add("You must select a PARENT for this new aggregation");
                            }

                            // Validate the code

                            if (new_aggregation_code.Length > 20)
                            {
                                errors.Add("New aggregation code must be twenty characters long or less");
                            }
                            else if (new_aggregation_code.Length == 0)
                            {
                                errors.Add("You must enter a CODE for this item aggregation");
                            }
                            else if (UI_ApplicationCache_Gateway.Aggregations[new_aggregation_code.ToUpper()] != null)
                            {
                                errors.Add("New code must be unique... <i>" + new_aggregation_code + "</i> already exists");
                            }
                            else if (UI_ApplicationCache_Gateway.Settings.Static.Reserved_Keywords.Contains(new_aggregation_code.ToLower()))
                            {
                                errors.Add("That code is a system-reserved keyword.  Try a different code.");
                            }
                            else
                            {
                                bool alphaNumericTest = new_aggregation_code.All(C => Char.IsLetterOrDigit(C) || C == '_' || C == '-');
                                if (!alphaNumericTest)
                                {
                                    errors.Add("New aggregation code must be only letters and numbers");
                                    new_aggregation_code = new_aggregation_code.Replace("\"", "");
                                }
                            }

                            // Was there a type and name
                            if (new_type.Length == 0)
                            {
                                errors.Add("You must select a TYPE for this new aggregation");
                            }
                            if (new_description.Length == 0)
                            {
                                errors.Add("You must enter a DESCRIPTION for this new aggregation");
                            }
                            if (new_name.Length == 0)
                            {
                                errors.Add("You must enter a NAME for this new aggregation");
                            }
                            else
                            {
                                if (new_shortname.Length == 0)
                                {
                                    new_shortname = new_name;
                                }
                            }

                            if (errors.Count > 0)
                            {
                                // Create the error message
                                actionMessage = "ERROR: Invalid entry for new item aggregation<br />";
                                foreach (string error in errors)
                                {
                                    actionMessage = actionMessage + "<br />" + error;
                                }

                                // Save all the values that were entered
                                enteredCode            = new_aggregation_code;
                                enteredDescription     = new_description;
                                enteredIsActive        = is_active;
                                enteredIsHidden        = is_hidden;
                                enteredName            = new_name;
                                enteredParent          = new_parent;
                                enteredShortname       = new_shortname;
                                enteredType            = new_type;
                                enteredLink            = new_link;
                                enteredThematicHeading = new_thematic_heading;
                            }
                            else
                            {
                                // Get the correct type
                                string correct_type = "Collection";
                                switch (new_type)
                                {
                                case "coll":
                                    correct_type = "Collection";
                                    break;

                                case "group":
                                    correct_type = "Collection Group";
                                    break;

                                case "subcoll":
                                    correct_type = "SubCollection";
                                    break;

                                case "inst":
                                    correct_type = "Institution";
                                    break;

                                case "exhibit":
                                    correct_type = "Exhibit";
                                    break;

                                case "subinst":
                                    correct_type = "Institutional Division";
                                    break;
                                }
                                // Make sure inst and subinst start with 'i'
                                if (new_type.IndexOf("inst") >= 0)
                                {
                                    if (new_aggregation_code[0] == 'I')
                                    {
                                        new_aggregation_code = "i" + new_aggregation_code.Substring(1);
                                    }
                                    if (new_aggregation_code[0] != 'i')
                                    {
                                        new_aggregation_code = "i" + new_aggregation_code;
                                    }
                                }

                                // Get the thematic heading id (no checks here)
                                string thematicHeading = null;
                                if (form["admin_aggr_heading"] != null)
                                {
                                    int thematicHeadingId = Convert.ToInt32(form["admin_aggr_heading"]);
                                    foreach (Thematic_Heading thisHeading in UI_ApplicationCache_Gateway.Thematic_Headings)
                                    {
                                        if (thisHeading.ID == thematicHeadingId)
                                        {
                                            thematicHeading = thisHeading.Text;
                                            break;
                                        }
                                    }
                                }

                                // Create the new aggregation argument object
                                New_Aggregation_Arguments args = new New_Aggregation_Arguments
                                {
                                    Active           = is_active,
                                    Code             = new_aggregation_code,
                                    Description      = new_description,
                                    External_Link    = enteredLink,
                                    Hidden           = is_hidden,
                                    Name             = new_name,
                                    ParentCode       = new_parent,
                                    ShortName        = new_shortname,
                                    Thematic_Heading = thematicHeading,
                                    Type             = correct_type,
                                    User             = RequestSpecificValues.Current_User.Full_Name
                                };

                                // Try to add this aggregation
                                RestResponseMessage msg = SobekEngineClient.Aggregations.Add_New_Aggregation(args);

                                // We are going to save some of the values here anyway, to assist with bulk adds
                                enteredIsActive        = is_active;
                                enteredIsHidden        = is_hidden;
                                enteredParent          = new_parent;
                                enteredType            = new_type;
                                enteredLink            = new_link;
                                enteredThematicHeading = new_thematic_heading;

                                if (msg.ErrorTypeEnum == ErrorRestTypeEnum.Successful)
                                {
                                    RequestSpecificValues.Current_Mode.Mode        = Display_Mode_Enum.Aggregation;
                                    RequestSpecificValues.Current_Mode.Aggregation = new_aggregation_code;
                                    actionMessage = "New item aggregation (" + new_aggregation_code.ToUpper() + ") saved successfully.<br /><br /><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode, true) + "\" target=\"" + new_aggregation_code + "_AGGR\">Click here to view the new aggregation</a>";
                                    RequestSpecificValues.Current_Mode.Mode       = Display_Mode_Enum.Administrative;
                                    RequestSpecificValues.Current_Mode.Admin_Type = Admin_Type_Enum.Aggregations_Mgmt;

                                    // Clear all aggregation information (and thematic heading info) from the cache as well
                                    CachedDataManager.Aggregations.Clear();
                                }
                                else
                                {
                                    actionMessage      = msg.Message;
                                    enteredCode        = new_aggregation_code;
                                    enteredShortname   = new_shortname;
                                    enteredName        = new_name;
                                    enteredDescription = new_description;
                                }
                            }
                        }
                    }
                }
                catch
                {
                    actionMessage = "General error while reading postback information";
                }
            }
        }
Beispiel #24
0
 /// <summary>
 /// Decrement the current load
 /// </summary>
 public void BeforeSendResponse(RestResponseMessage response)
 {
     Interlocked.Decrement(ref this.m_currentLoad);
 }
Beispiel #25
0
        /// <summary>
        /// Dispatch the HttpRequest message to the appropriate service
        /// </summary>
        internal bool Dispatch(ServiceDispatcher serviceDispatcher, RestRequestMessage requestMessage, RestResponseMessage responseMessage)
        {
            // Allow message inspectors to inspect the message before next stage
            try
            {
                this.m_traceSource.TraceEvent(TraceEventType.Verbose, 0, "Begin endpoint dispatch of {0} {1} > {2}", requestMessage.Method, requestMessage.Url, this.m_serviceEndpoint.Description.Contract);

                foreach (var mfi in this.m_messageInspector)
                {
                    mfi.AfterReceiveRequest(requestMessage);
                }

                var ops = this.m_serviceEndpoint.Operations.Where(o => o.Dispatcher.CanDispatch(requestMessage));
                if (ops.Count() == 0)
                {
                    throw new FaultException(404, $"Resource not Found - {requestMessage.Url.AbsolutePath}");
                }
                var op = ops.FirstOrDefault(o => requestMessage.Method.ToLowerInvariant() == o.Description.Method.ToLowerInvariant());
                if (op == null)
                {
                    throw new FaultException(405, "Method not permitted");
                }

                RestOperationContext.Current.EndpointOperation = op;
                op.Dispatcher.Dispatch(serviceDispatcher, requestMessage, responseMessage);

                // Allow message inspectors to inspect before sending response
                foreach (var mfi in this.m_messageInspector)
                {
                    mfi.BeforeSendResponse(responseMessage);
                }

                return(true);
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, e.ToString());
                return(serviceDispatcher.HandleFault(e, responseMessage));
            }
        }
        /// <summary>
        /// Serialize the reply
        /// </summary>
        public void SerializeResponse(RestResponseMessage responseMessage, object[] parameters, object result)
        {
            try
            {
                // Outbound control
                var    httpRequest = RestOperationContext.Current.IncomingRequest;
                string accepts     = httpRequest.Headers["Accept"],
                       contentType = httpRequest.Headers["Content-Type"],
                       formatParm  = httpRequest.QueryString["_format"];

                var isOutputPretty = httpRequest.QueryString["_pretty"] == "true";

                SummaryType?summaryType = SummaryType.False;
                if (httpRequest.QueryString["_summary"] != null)
                {
                    summaryType = EnumUtility.ParseLiteral <SummaryType>(httpRequest.QueryString["_summary"], true);
                }

                if (accepts == "*/*") // Any = null
                {
                    accepts = null;
                }

                contentType = accepts ?? contentType ?? formatParm;

                // No specified content type
                if (string.IsNullOrEmpty(contentType))
                {
                    contentType = this.m_configuration.DefaultResponseFormat == FhirResponseFormatConfiguration.Json ? "application/fhir+json" : "application/fhir+xml";
                }

                var charset = ContentType.GetCharSetFromHeaderValue(contentType);
                var format  = ContentType.GetMediaTypeFromHeaderValue(contentType);

                if (result is Base baseObject)
                {
                    var ms = new MemoryStream();
                    // The request was in JSON or the accept is JSON
                    switch (format)
                    {
                    case "application/fhir+xml":
                        using (var xw = XmlWriter.Create(ms, new XmlWriterSettings
                        {
                            Encoding = new UTF8Encoding(false),
                            Indent = isOutputPretty
                        }))
                        {
                            new FhirXmlSerializer().Serialize(baseObject, xw, summaryType.Value);
                        }

                        break;

                    case "application/fhir+json":
                        using (var sw = new StreamWriter(ms, new UTF8Encoding(false), 1024, true))
                            using (var jw = new JsonTextWriter(sw)
                            {
                                Formatting = isOutputPretty ? Formatting.Indented : Formatting.None,
                                DateFormatHandling = DateFormatHandling.IsoDateFormat
                            })
                            {
                                new FhirJsonSerializer(new SerializerSettings
                                {
                                    Pretty = isOutputPretty
                                }).Serialize(baseObject, jw);
                            }

                        break;

                    default:
                        throw new FhirException((HttpStatusCode)406, OperationOutcome.IssueType.NotSupported, $"{contentType} not supported");
                    }

                    ms.Seek(0, SeekOrigin.Begin);
                    responseMessage.Body = ms;
                }
                else if (result == null)
                {
                    responseMessage.StatusCode = 204; // no content
                }
                else
                {
                    throw new InvalidOperationException("FHIR return values must inherit from Base");
                }

                RestOperationContext.Current.OutgoingResponse.ContentType = contentType;
                RestOperationContext.Current.OutgoingResponse.AppendHeader("X-PoweredBy", string.Format("{0} v{1} ({2})", Assembly.GetEntryAssembly().GetName().Name, Assembly.GetEntryAssembly().GetName().Version, Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion));
                RestOperationContext.Current.OutgoingResponse.AppendHeader("X-GeneratedOn", DateTime.Now.ToString("o"));
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
                throw;
            }
        }
 /// <summary>
 /// Before sending a response
 /// </summary>
 public void BeforeSendResponse(RestResponseMessage response)
 {
     // Decrement our instance
     Interlocked.Decrement(ref this.m_requests);
 }
        /// <summary>
        /// Provide a fault
        /// </summary>
        public bool ProvideFault(Exception error, RestResponseMessage response)
        {
            this.m_tracer.TraceEvent(EventLevel.Error, "Error on WCF FHIR Pipeline: {0}", error);

            // Get to the root of the error
            while (error.InnerException != null)
            {
                error = error.InnerException;
            }

            // Formulate appropriate response
            if (error is DomainStateException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.ServiceUnavailable;
            }
            else if (error is PolicyViolationException)
            {
                var pve = error as PolicyViolationException;
                if (pve.PolicyDecision == PolicyGrantType.Elevate)
                {
                    // Ask the user to elevate themselves
                    RestOperationContext.Current.OutgoingResponse.StatusCode = 401;
                    var authHeader = $"{(RestOperationContext.Current.AppliedPolicies.Any(o=>o.GetType().Name.Contains("Basic")) ? "Basic" : "Bearer")} realm=\"{RestOperationContext.Current.IncomingRequest.Url.Host}\" error=\"insufficient_scope\" scope=\"{pve.PolicyId}\"  error_description=\"{error.Message}\"";
                    RestOperationContext.Current.OutgoingResponse.AddHeader("WWW-Authenticate", authHeader);
                }
                else
                {
                    RestOperationContext.Current.OutgoingResponse.StatusCode = 403;
                }
            }
            else if (error is SecurityException || error is UnauthorizedAccessException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            }
            else if (error is SecurityTokenException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                RestOperationContext.Current.OutgoingResponse.AddHeader("WWW-Authenticate", $"Bearer");
            }
            else if (error is FaultException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)(error as FaultException).StatusCode;
            }
            else if (error is Newtonsoft.Json.JsonException ||
                     error is System.Xml.XmlException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
            }
            else if (error is FileNotFoundException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
            }
            else if (error is DbException || error is ConstraintException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)(System.Net.HttpStatusCode) 422;
            }
            else if (error is PatchException)
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.Conflict;
            }

            else
            {
                RestOperationContext.Current.OutgoingResponse.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
            }

            // Construct an error result
            var errorResult = new OperationOutcome()
            {
                Issue = new List <Issue>()
                {
                    new Issue()
                    {
                        Diagnostics = error.Message, Severity = IssueSeverity.Error, Code = new FhirCoding(new Uri("http://hl7.org/fhir/issue-type"), "exception")
                    }
                }
            };

            if (error is DetectedIssueException)
            {
                foreach (var iss in (error as DetectedIssueException).Issues)
                {
                    errorResult.Issue.Add(new Issue()
                    {
                        Diagnostics = iss.Text,
                        Severity    = iss.Priority == DetectedIssuePriorityType.Error ? IssueSeverity.Error :
                                      iss.Priority == DetectedIssuePriorityType.Warning ? IssueSeverity.Warning :
                                      IssueSeverity.Information
                    });
                }
            }
            // Return error in XML only at this point
            new FhirMessageDispatchFormatter().SerializeResponse(response, null, errorResult);
            return(true);
        }
Beispiel #29
0
        /// <summary>
        /// Default serialization of the response
        /// </summary>
        public void SerializeResponse(RestResponseMessage responseMessage, object[] parameters, object result)
        {
            var         acceptHeader = RestOperationContext.Current.IncomingRequest.Headers["Accept"];
            ContentType contentType  = null;

            if (!String.IsNullOrEmpty(acceptHeader))
            {
                contentType = acceptHeader.Split(',').Select(o => new ContentType(o)).First();
            }

            // By default unless Accept is application/json , we always prefer application/xml
            if (result == null)
            {
                if (responseMessage.StatusCode == 200)
                {
                    responseMessage.StatusCode = 204;
                }
            }
            else if (result is Stream)
            {
                responseMessage.ContentType = responseMessage.ContentType ?? "application/octet-stream";
                responseMessage.Body        = result as Stream;
            }
            else if (result.GetType().IsPrimitive || result is string ||
                     result is Guid)
            {
                var ms = new MemoryStream(Encoding.UTF8.GetBytes(result.ToString()));
                responseMessage.ContentType = responseMessage.ContentType ?? "text/plain";
                responseMessage.Body        = ms;
            }
            else if (responseMessage.Format == MessageFormatType.Json ||
                     contentType?.MediaType == "application/json" ||
                     RestOperationContext.Current.IncomingRequest.Url.AbsolutePath.EndsWith(".json"))
            {
                // Prepare the serializer
                JsonSerializer jsz = new JsonSerializer();
                var            ms  = new MemoryStream();
                using (var tms = new MemoryStream())
                    using (StreamWriter sw = new StreamWriter(tms, new UTF8Encoding(false)))
                        using (JsonWriter jsw = new JsonTextWriter(sw))
                        {
                            jsz.DateFormatHandling    = DateFormatHandling.IsoDateFormat;
                            jsz.NullValueHandling     = NullValueHandling.Ignore;
                            jsz.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                            jsz.TypeNameHandling      = TypeNameHandling.Auto;
                            jsz.Converters.Add(new StringEnumConverter());
                            jsz.Serialize(jsw, result);
                            jsw.Flush();
                            sw.Flush();
                            tms.Seek(0, SeekOrigin.Begin);
                            tms.CopyTo(ms);
                        }
                ms.Seek(0, SeekOrigin.Begin);
                responseMessage.ContentType = responseMessage.ContentType ?? "application/json";
                responseMessage.Body        = ms;
            }
            else if (responseMessage.Format == MessageFormatType.Xml ||
                     contentType?.MediaType == "application/xml" ||
                     RestOperationContext.Current.IncomingRequest.Url.AbsolutePath.EndsWith(".xml"))
            {
                if (typeof(ExpandoObject).IsAssignableFrom(result.GetType()) ||
                    typeof(IEnumerable <ExpandoObject>).IsAssignableFrom(result.GetType()))
                {
                    // Custom serialization for XML of a dynamic
                    if (result.GetType() == typeof(ExpandoObject))
                    {
                        result = new List <ExpandoObject>()
                        {
                            result as ExpandoObject
                        }
                    }
                    ;
                    var ms = new MemoryStream();
                    using (var xw = XmlWriter.Create(ms, new XmlWriterSettings()
                    {
                        CloseOutput = false
                    }))                                                                                    // Write dynamic
                    {
                        xw.WriteStartElement("ArrayOfDynamic", "http://tempuri.org");
                        // Iterate through objects
                        foreach (var itm in result as IEnumerable)
                        {
                            xw.WriteStartElement("item", "http://tempuri.org");
                            foreach (var prop in itm as ExpandoObject)
                            {
                                xw.WriteStartElement(prop.Key);
                                if (prop.Value is Guid)
                                {
                                    xw.WriteValue(prop.Value.ToString());
                                }
                                else if (prop.Value != null)
                                {
                                    xw.WriteValue(prop.Value);
                                }
                                xw.WriteEndElement();
                            }
                            xw.WriteEndElement();
                        }
                        xw.WriteEndElement();
                    }

                    ms.Seek(0, SeekOrigin.Begin);
                    responseMessage.ContentType = responseMessage.ContentType ?? "application/xml";
                    responseMessage.Body        = ms;
                }
                else
                {
                    if (!this.m_serializers.TryGetValue(result.GetType(), out XmlSerializer serializer))
                    {
                        serializer = new XmlSerializer(result.GetType());
                        this.m_serializers.TryAdd(result.GetType(), serializer);
                    }
                    var ms = new MemoryStream();
                    serializer.Serialize(ms, result);
                    ms.Seek(0, SeekOrigin.Begin);
                    responseMessage.ContentType = responseMessage.ContentType ?? "application/xml";
                    responseMessage.Body        = ms;
                }
            }
            else
            {
                throw new ArgumentException($"Unsupported response format requested");
            }
        }
    }
 public void BeforeSendResponse(RestResponseMessage response)
 {
     Console.WriteLine("RSP: {0} ({1})", sessionId, response.StatusCode);
 }